﻿using DBUtil.MetaData;
using DotNetCommon.Extensions;
using LiveCharts;
using LiveCharts.Wpf;
using log4net;
using Microsoft.Office.Interop.Excel;
using Newtonsoft.Json;
using Sunny.UI;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Configuration;
using System.Data;
using System.Diagnostics.CodeAnalysis;
using System.Net;
using System.Net.Mail;
using System.Net.Sockets;
using System.Numerics;
using System.Threading;
using System.Threading.Channels;
using TencentCloud.Common;
using TencentCloud.Common.Profile;
using TencentCloud.Sms.V20210111;
using TencentCloud.Sms.V20210111.Models;
using static System.Runtime.InteropServices.JavaScript.JSType;
using DataTable = System.Data.DataTable;
using Excel = Microsoft.Office.Interop.Excel;
using File = System.IO.File;
using MessageBox = System.Windows.Forms.MessageBox;

enum SENSOR_TYPE : int
{
    NORMAL_SENSOR = 0, STRAIN_SENSOR, TEMPER_SENSOR, DISPLACE_SENSOR
};

namespace JFBG
{
    public partial class Page1 : UIPage
    {
        private static readonly ILog log = LogManager.GetLogger(typeof(Page1));

        //监听线程
        [DisallowNull]
        public static Thread receiveThread1;

        bool debug = true;
        //X轴值数量初始值
        private long xCount = 1000;
        //X轴值最大计数值
        private long xTimes = 0;
        //显示时长
        //private long showTimes = 60;//(秒)
        //当前时间
        private long lastTime = DateTimeOffset.Now.ToUnixTimeMilliseconds();
        private long lastTime1 = DateTimeOffset.Now.ToUnixTimeMilliseconds();
        private long lastTime2 = DateTimeOffset.Now.ToUnixTimeMilliseconds();
        private long lastTime3 = DateTimeOffset.Now.ToUnixTimeMilliseconds();
        //采样频率
        private long frequency = 1000;
        //采集间隔
        private long intervalTime = 1000;//(毫秒)
        //通道初始值
        private int channelIndex = 0;
        //通道初始值
        private int rasterIndex = 0;
        //光栅总数
        private int rasterCount = 16;
        //通道总数
        private int channelCount = 16;
        private Random R { get; set; }//为了给Y值提供随机值
        //定时刷新曲线
        private System.Windows.Forms.Timer timerChart;

        //普通传感器 0
        //应变传感器 1
        //倾角传感器 2
        //加速度传感器 3
        //温度传感器 4
        //位移传感器 5
        //应力传感器 6
        //压力传感器 7
        //震动传感器 8
        //扭矩传感器 9
        //沉降传感器 10
        //声发射传感器 11

        private int sensorType = 0;

        private bool isSaveWaveToExcel = true;

        private static bool isSaveDataToMysql = true;

        private static string waveFilePath = "D:\\聚芯光纤\\";

        private static string waveFileName = "波长数据";

        private static string waveFileNameDate = "";

        [DisallowNull]
        private Excel.Application excelApp;

        [DisallowNull]
        private Excel._Workbook workbook;

        //[DisallowNull]
        //private FileStream fs;

        [DisallowNull]
        private StreamWriter sw;

        private string filePath;

        private bool isWaveCollectTimes = false;

        private int waveCollectTimes = 0;

        private List<ColumnData> dataList = new List<ColumnData>();

        //轴力超过阈值次数
        private static int axialAlarmRepeatTimes = 0;

        private static bool isAlarmNotify = true;
        private static double axialForceExceeds = 8000.0;
        private static int repeatTimes = 100;

        private static bool isAlarmEmail = true;
        private static string alarmEmail = "";

        private static bool isAlarmPhone = true;
        private static string alarmPhone = "";

        //温度传感器初始光栅波长
        private static double tempStartWave = 1550.110;
        //温度传感器初始温度
        private static double tempStartValue = 25;

        private Dictionary<int, Dictionary<int, SensorEntity>> entityList = new Dictionary<int, Dictionary<int, SensorEntity>>();

        private static string mqttIP = "10.168.1.102";//"q6c296c9.natappfree.cc"; //"qd731d03.ala.cn-hangzhou.emqxsl.cn";
        private static int mqttPort = 12803;//7607; //8883;
        private static string mqttUser = "caoejiang_mqtt";
        private static string mqttPwd = "caoejiang";
        private static string mqttTopic = "twenty_one_gate_data";
        private static string clientId = "caoejiang_21";
        private static bool IsStop = false;

        private MqttClientManage? mqttClientManage = null;

        private string rasterTableName = "raster_wave_normal";
        private string sensorTableName = "sensor_device_data";
        private int timeoutSeconds = 60 * 30;
        private int notifyAfter = 0;
        private Func<long, Task<bool>> callBack;
        private CancellationToken cancellationToken = default;
        ConcurrentQueue<List<SensorWaveData>> queue = new ConcurrentQueue<List<SensorWaveData>>();

        public Page1()
        {
            InitializeComponent();

            InitChartConfig();

            #region  多Y轴曲线
            //将自定义类型MeasureModel映射到曲线坐标点
            var mapper = LiveCharts.Configurations.Mappers.Xy<DateTimePoint>()
              .X(model => model.Time)    //使用 Time.作为X轴的标签
              .Y(model => model.Value);  //使用Value 作为Y轴的值

            //全局保存映射器
            Charting.For<DateTimePoint>(mapper);
            #endregion

            this.cbWaveChannelSellect.SelectedIndex = Convert.ToInt32(ConfigurationManager.AppSettings["cbWaveChannelSellect"]);
            this.cbWaveSensorSellect.SelectedIndex = Convert.ToInt32(ConfigurationManager.AppSettings["cbWaveSensorSellect"]);
            this.cbWaveSensorType.SelectedIndex = Convert.ToInt32(ConfigurationManager.AppSettings["cbWaveSensorType"]);
            this.tbWaveFrequency.Text = ConfigurationManager.AppSettings["tbWaveFrequency"];
            this.cbWaveCollectTimes.Checked = Convert.ToBoolean(ConfigurationManager.AppSettings["cbWaveCollectTimes"]);
            this.tbWaveCollectTimes.Text = ConfigurationManager.AppSettings["tbWaveCollectTimes"];
            this.cbSaveWaveExcel.Checked = Convert.ToBoolean(ConfigurationManager.AppSettings["cbSaveWaveExcel"]);

            waveFilePath = ConfigurationManager.AppSettings["tbWaveFilePath"];

            waveFileName = ConfigurationManager.AppSettings["waveFileName"];

            this.tbWaveFilePath.Text = waveFilePath;

            isSaveDataToMysql = Convert.ToBoolean(ConfigurationManager.AppSettings["isSaveDataToMysql"]);

            isAlarmNotify = Convert.ToBoolean(ConfigurationManager.AppSettings["cbAlarmNotify"]);

            axialForceExceeds = Convert.ToDouble(ConfigurationManager.AppSettings["tbAxialForceExceeds"]);

            repeatTimes = Convert.ToInt16(ConfigurationManager.AppSettings["tbRepeatTimes"]);

            isAlarmPhone = Convert.ToBoolean(ConfigurationManager.AppSettings["cbAlarmPhone"]);

            alarmPhone = ConfigurationManager.AppSettings["tbAlarmPhone"];

            isAlarmEmail = Convert.ToBoolean(ConfigurationManager.AppSettings["cbAlarmEmail"]);

            alarmEmail = ConfigurationManager.AppSettings["tbAlarmEmail"];

            tempStartWave = Convert.ToDouble(ConfigurationManager.AppSettings["tempStartWave"]);

            tempStartValue = Convert.ToDouble(ConfigurationManager.AppSettings["tempStartValue"]);

            mqttIP = ConfigurationManager.AppSettings["MqttIP"];

            mqttPort = Convert.ToInt16(ConfigurationManager.AppSettings["MqttPort"]);

            mqttUser = ConfigurationManager.AppSettings["MqttUser"];

            mqttPwd = ConfigurationManager.AppSettings["MqttPwd"];

            mqttTopic = ConfigurationManager.AppSettings["MqttTopic"];

            clientId = ConfigurationManager.AppSettings["ClientId"];


            //CreateExcelDataFile();

            if (this.tbWaveFrequency.Text.Length > 0)
            {
                long _frequency = Convert.ToInt64(this.tbWaveFrequency.Text);
                //转换成长整型
                if (this.frequency != _frequency)
                {
                    this.frequency = _frequency;
                    //this.intervalTime = 1000 / this.frequency;
                    //this.xCount = this.showTimes * this.frequency;
                    this.xCount = this.frequency;
                }
            }

            for (int i = 0; i < channelCount; i++)
            {
                ColumnData columnData = new ColumnData();
                dataList.Add(columnData);
            }
            uiDataGridView1.DataSource = dataList;

            uiDataGridView1.ReadOnly = true;

            this.debug = this.cbSimulationTest.Checked;
            R = new Random();

            //定时器刷新
            this.timerChart = new System.Windows.Forms.Timer()
            {
                Interval = (int)(this.intervalTime)
            };
            this.timerChart.Tick += TimerChart_Tick;
            this.timerChart.Start();

            //开启接收消息线程
            //receiveThread1 = new Thread(ReceiveMessage);
            //receiveThread1.Start();

            var sql = @"select * from sensor_table";
            var dt = MainForm.db.SelectDataTable(sql);

            for (int i = 0; i < dt.Rows.Count; i++)
            {
                var row = dt.Rows[i];
                SensorEntity sensorEntity = new SensorEntity()
                {
                    ID = (int)row["ID"],
                    SensorName = row["SensorName"].ToString(),
                    SensorType = (int)row["SensorType"],
                    ChannelIndex = (int)row["ChannelIndex"],
                    SensorIndex = (int)row["SensorIndex"],
                    WaveCount = (int)row["WaveCount"],
                    Expression = row["Expression"].ToString(),
                    Description = row["Description"].ToString(),
                    Param1 = row["Param1"].ToString(),
                    Param2 = row["Param2"].ToString(),
                    Param3 = row["Param3"].ToString(),
                    Param4 = row["Param4"].ToString(),
                    Param5 = row["Param5"].ToString(),
                    Param6 = row["Param6"].ToString(),
                    Param7 = row["Param7"].ToString(),
                    Param8 = row["Param8"].ToString(),
                    Param9 = row["Param9"].ToString(),
                    Param10 = row["Param10"].ToString(),
                    Param11 = row["Param11"].ToString(),
                    Param12 = row["Param12"].ToString(),
                    Param13 = row["Param13"].ToString(),
                    Param14 = row["Param14"].ToString(),
                    Param15 = row["Param15"].ToString(),
                    Param16 = row["Param16"].ToString()
                };
                if (entityList.ContainsKey((int)row["ChannelIndex"]))
                {
                    Dictionary<int, SensorEntity> entityMap = new Dictionary<int, SensorEntity>();
                    entityList.TryGetValue((int)row["ChannelIndex"], out entityMap);
                    entityMap.Add((int)row["SensorIndex"], sensorEntity);
                    entityList.AddOrUpdate((int)row["ChannelIndex"], entityMap);
                }
                else
                {
                    Dictionary<int, SensorEntity> entityMap = new Dictionary<int, SensorEntity>();
                    entityMap.Add((int)row["SensorIndex"], sensorEntity);
                    entityList.Add((int)row["ChannelIndex"], entityMap);
                }
            }
            clientId = string.IsNullOrEmpty(clientId) ? Guid.NewGuid().ToString() : clientId;
            mqttClientManage = new MqttClientManage();
            if (mqttClientManage != null)
            {
                mqttClientManage.ConnectAsync(mqttIP, mqttPort, mqttUser, mqttPwd, clientId);
                mqttClientManage.SubscribeAsync(mqttTopic);
            }
        }

        public async Task MqttDataPublic(List<DeviceData> deviceDataList)
        {
            //JsonArray jsonArray = new JsonArray(deviceDataList);
            // 将List转换为JSON字符串
            string jsonString = JsonConvert.SerializeObject(deviceDataList);
            if (mqttClientManage != null)
            {
                await mqttClientManage.PublishAsync(mqttTopic, jsonString);
            }
        }

        //窗口关闭事件委托，在窗口关闭事件前处理
        private void Page1_FormClosing(object sender, FormClosingEventArgs e)
        {
            if (receiveThread1 != null)
            {
                receiveThread1.Interrupt();
            }
            //if (this.isSaveWaveToExcel)
            //{
            //    if (this.excelApp != null)
            //    {
            //        this.excelApp.DisplayAlerts = false;
            //        if (this.workbook != null)
            //        {
            //            this.workbook.Close(false);
            //            this.workbook = null;
            //        }
            //        this.excelApp.Quit();
            //        this.excelApp = null;
            //    }
            //}
            //fs.Close();
            //fs.Dispose();
            sw.Close();
            sw.Dispose();
            sw = null;
        }

        private void TimerChart_Tick(object sender, EventArgs e)
        {
            //if (this.debug)
            //{
            //    StackedAreaSeriesRefresh();
            //}
            long startTime = new DateTimeOffset(DateTime.UtcNow).ToUnixTimeMilliseconds();
            log.Debug("TimerChart_Tick start timestamp = " + startTime);
            Task consumer = Task.Run(() =>
            {
                List<List<SensorWaveData>> sensorWaveDataLists = new List<List<SensorWaveData>>();
                while (!queue.IsEmpty)
                {
                    if (queue.TryDequeue(out List<SensorWaveData> sensorWaveDataList))
                    {
                        sensorWaveDataLists.Add(sensorWaveDataList);
                        
                    }
                }
                if (sensorWaveDataLists.Count > 0)
                {
                    DataTableProcess(sensorWaveDataLists);
                    sensorWaveDataLists.Clear();
                    sensorWaveDataLists = null;
                }
            });
            long endTime = new DateTimeOffset(DateTime.UtcNow).ToUnixTimeMilliseconds();
            log.Debug("TimerChart_Tick end timestamp = " + endTime);
        }

        private void DataTableProcess(List<List<SensorWaveData>> sensorWaveDataLists)
        {
            try
            {
                //<chnanelId, <waveId, List<value>>>
                Dictionary<int, Dictionary<int, List<double>>> channelWaveDictionarys = new Dictionary<int, Dictionary<int, List<double>>>();
                foreach (List<SensorWaveData> sensorWaveDatas in sensorWaveDataLists)
                {
                    foreach (SensorWaveData sensorWaveData in sensorWaveDatas)
                    {
                        if (channelWaveDictionarys.TryGetValue(sensorWaveData.channelId, out Dictionary<int, List<double>> waveDictionary))
                        {
                            for (int index = 0; index < sensorWaveData.waveCnt; index++)
                            {
                                if (waveDictionary.TryGetValue((index + 1), out List<double> waveList))
                                {
                                    waveList.Add(sensorWaveData.waveLengths[index]);
                                }
                                else
                                {
                                    waveList = new List<double>() { sensorWaveData.waveLengths[index] };
                                    waveDictionary.Add(index, waveList);
                                }
                            }
                        }
                        else
                        {
                            waveDictionary = new Dictionary<int, List<double>>();
                            for (int index = 0; index < sensorWaveData.waveCnt; index++)
                            {
                                List<double> waveList = new List<double>() { sensorWaveData.waveLengths[index] };
                                waveDictionary.Add(index, waveList);
                            }
                            channelWaveDictionarys.Add(sensorWaveData.channelId, waveDictionary);
                        }
                    }
                }
                List<SensorWaveData> sensorWaveDataList = new List<SensorWaveData>();
                // 遍历元素
                foreach (KeyValuePair<int, Dictionary<int, List<double>>> channelWaveDictionary in channelWaveDictionarys)
                {
                    log.Debug($"ID: {channelWaveDictionary.Key}, Name: {channelWaveDictionary.Value}");
                    SensorWaveData sensorWaveData = new SensorWaveData();
                    sensorWaveData.timestamp = DateTimeOffset.Now.ToUnixTimeMilliseconds(); ;
                    sensorWaveData.channelId = channelWaveDictionary.Key;
                    Dictionary<int, List<double>> waveDictionarys = channelWaveDictionary.Value;
                    sensorWaveData.waveCnt = waveDictionarys.Keys.Count;
                    sensorWaveData.waveLengths = new double[sensorWaveData.waveCnt];
                    foreach (KeyValuePair<int, List<double>> waveDictionary in waveDictionarys)
                    {
                        List<double> waveLengthList = waveDictionary.Value;
                        // 将n显式转换为double以避免整数除法问题
                        double averageWave = waveLengthList.Count > 0 ? waveLengthList.Average(n => (double)n) : 0;
                        sensorWaveData.waveLengths[waveDictionary.Key] = averageWave;
                    }
                    sensorWaveDataList.Add(sensorWaveData);
                }
                if (sensorWaveDataList.Count > 0)
                {
                    SensorWaveDataCalculate(sensorWaveDataList);
                    sensorWaveDataList.Clear();
                    sensorWaveDataList = null;
                }
                channelWaveDictionarys.Clear();
                channelWaveDictionarys = null;
            }
            catch (Exception ex)
            {
                log.Error(ex.Message);
            }
            finally
            {

            }
        }

        private void SensorWaveDataCalculate(List<SensorWaveData> sensorWaveDataList)
        {
            DataTable sensorTable = new DataTable();
            sensorTable.Columns.Add("collect_time", typeof(long));
            sensorTable.Columns.Add("collect_datetime", typeof(string));
            sensorTable.Columns.Add("channel_id", typeof(int));
            sensorTable.Columns.Add("sensor_type", typeof(int));
            sensorTable.Columns.Add("sensor_count", typeof(int));
            sensorTable.Columns.Add("sensor_index", typeof(int));
            sensorTable.Columns.Add("sensor_id", typeof(int));
            sensorTable.Columns.Add("sensor_name", typeof(string));
            sensorTable.Columns.Add("wave_length1", typeof(double));
            sensorTable.Columns.Add("wave_length2", typeof(double));
            sensorTable.Columns.Add("wave_length3", typeof(double));
            sensorTable.Columns.Add("wave_length4", typeof(double));
            sensorTable.Columns.Add("count_value1", typeof(double));
            sensorTable.Columns.Add("count_value2", typeof(double));
            sensorTable.Columns.Add("count_value3", typeof(double));
            sensorTable.Columns.Add("count_value4", typeof(double));

            List<DeviceData> deviceDataList = new List<DeviceData>();
            List<SensorDeviceData> sensorDeviceDataList = new List<SensorDeviceData>();
            foreach (SensorWaveData sensorWaveData in sensorWaveDataList)
            {
                int _sensorType = 0;
                long nowTime = sensorWaveData.timestamp;
                string datetime = (new DateTime(1970, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc).AddMilliseconds((long)nowTime).ToLocalTime()).ToString("yyyy-MM-dd HH:mm:ss");
                int channelId = sensorWaveData.channelId;
                int waveCnt = sensorWaveData.waveCnt;
                double[]waveLengths = sensorWaveData.waveLengths;

                if (entityList.ContainsKey(channelId))
                {
                    Dictionary<int, SensorEntity> entityMap = new Dictionary<int, SensorEntity>();
                    entityList.TryGetValue(channelId, out entityMap);
                    if (entityMap.Count > 0)
                    {
                        SensorEntity sensorEntity = new SensorEntity();
                        foreach (var item in entityMap)
                        {
                            sensorEntity = item.Value;
                            break;
                        }
                        _sensorType = sensorEntity.SensorType;
                        switch (sensorEntity.SensorType)
                        {
                            //应变传感器
                            case 1:
                                if ((waveCnt >= 2) && (waveCnt % 2 == 0) && (waveCnt < rasterCount))
                                //if(waveCnt == 8)
                                {
                                    for (int rasterID = 0; rasterID < waveCnt / 2; rasterID++)
                                    {
                                        if (rasterID >= 4)
                                        {
                                            break;
                                        }
                                        if (entityMap.ContainsKey(rasterID + 1))
                                        {
                                            entityMap.TryGetValue(rasterID + 1, out sensorEntity);
                                            //计算公式：ε＝[(W1-A1)-(W2-A2)/K2*K3]/K1
                                            double countValue = CalculateStress(waveLengths[waveCnt / 2 + rasterID], waveLengths[rasterID],
                                                Double.Parse(sensorEntity.Param1), Double.Parse(sensorEntity.Param2), Double.Parse(sensorEntity.Param3), Double.Parse(sensorEntity.Param4), Double.Parse(sensorEntity.Param5));

                                            sensorTable.Rows.Add(nowTime, datetime, channelId, sensorEntity.SensorType, waveCnt / 2, rasterID, sensorEntity.ID, sensorEntity.SensorName, waveLengths[waveCnt / 2 + rasterID], waveLengths[rasterID], 0, 0, countValue, 0, 0, 0);
                                            DeviceData deviceData = new DeviceData();
                                            deviceData.deviceId = sensorEntity.ID;
                                            deviceData.deviceType = sensorEntity.SensorType;
                                            deviceData.name = sensorEntity.SensorName;
                                            deviceData.timestamp = nowTime;
                                            deviceData.value = countValue;
                                            deviceData.wave1 = waveLengths[waveCnt / 2 + rasterID];
                                            deviceData.wave2 = waveLengths[rasterID];
                                            deviceDataList.Add(deviceData);
                                            //if ((nowTime - this.lastTime1) > this.intervalTime)
                                            //{
                                            SensorDeviceData sensorDeviceData = new SensorDeviceData();
                                            sensorDeviceData.collect_datetime = datetime;
                                            sensorDeviceData.collect_time = nowTime;
                                            sensorDeviceData.channel_id = channelId;
                                            sensorDeviceData.sensor_type = sensorEntity.SensorType;
                                            sensorDeviceData.sensor_count = waveCnt / 2;
                                            sensorDeviceData.sensor_index = rasterID;
                                            sensorDeviceData.sensor_id = sensorEntity.ID;
                                            sensorDeviceData.sensor_name = sensorEntity.SensorName;
                                            sensorDeviceData.count_value1 = countValue;
                                            sensorDeviceData.wave_length1 = waveLengths[waveCnt / 2 + rasterID];
                                            sensorDeviceData.wave_length2 = waveLengths[rasterID];
                                            sensorDeviceDataList.Add(sensorDeviceData);

                                            if ((channelId == this.channelIndex) && (rasterID == this.rasterIndex))
                                            {
                                                ChartValues<DateTimePoint> chartValues = new ChartValues<DateTimePoint>();
                                                chartValues.Add(new DateTimePoint(nowTime, countValue));
                                                ChartLineRefresh(channelIndex, chartValues);
                                            }
                                            //this.lastTime1 = nowTime;
                                            //}
                                        }
                                    }
                                }
                                break;
                            case 2://倾角传感器
                                   //if ((waveCnt >= 2) && (waveCnt % 2 == 0) && (waveCnt < rasterCount))
                                if (waveCnt == 4)
                                {
                                    for (int rasterID = 0; rasterID < waveCnt / 2; rasterID++)
                                    {
                                        if (entityMap.ContainsKey(rasterID + 1))
                                        {
                                            entityMap.TryGetValue(rasterID + 1, out sensorEntity);
                                            //计算公式：a=[(Wa-Wa0)-(Wb-Wb0)]/K
                                            double countValue = CalculateAngle(waveLengths[2 * rasterID], waveLengths[2 * rasterID + 1],
                                                Double.Parse(sensorEntity.Param1), Double.Parse(sensorEntity.Param2), Double.Parse(sensorEntity.Param3));
                                            sensorTable.Rows.Add(nowTime, datetime, channelId, sensorEntity.SensorType, waveCnt / 2, rasterID, sensorEntity.ID, sensorEntity.SensorName, waveLengths[2 * rasterID], waveLengths[2 * rasterID + 1], 0, 0, countValue, 0, 0, 0);
                                            DeviceData deviceData = new DeviceData();
                                            deviceData.deviceId = sensorEntity.ID;
                                            deviceData.deviceType = sensorEntity.SensorType;
                                            deviceData.name = sensorEntity.SensorName;
                                            deviceData.timestamp = nowTime;
                                            deviceData.value = countValue;
                                            deviceData.wave1 = waveLengths[2 * rasterID];
                                            deviceData.wave2 = waveLengths[2 * rasterID + 1];
                                            deviceDataList.Add(deviceData);
                                            //if ((nowTime - this.lastTime2) > this.intervalTime)
                                            //{
                                            SensorDeviceData sensorDeviceData = new SensorDeviceData();
                                            sensorDeviceData.collect_datetime = datetime;
                                            sensorDeviceData.collect_time = nowTime;
                                            sensorDeviceData.channel_id = channelId;
                                            sensorDeviceData.sensor_count = waveCnt / 2;
                                            sensorDeviceData.sensor_index = rasterID;
                                            sensorDeviceData.sensor_id = sensorEntity.ID; ;
                                            sensorDeviceData.sensor_type = sensorEntity.SensorType;
                                            sensorDeviceData.sensor_name = sensorEntity.SensorName;
                                            sensorDeviceData.count_value1 = countValue;
                                            sensorDeviceData.wave_length1 = waveLengths[2 * rasterID];
                                            sensorDeviceData.wave_length2 = waveLengths[2 * rasterID + 1];
                                            sensorDeviceDataList.Add(sensorDeviceData);

                                            if ((channelId == this.channelIndex) && (rasterID == this.rasterIndex))
                                            {
                                                ChartValues<DateTimePoint> chartValues = new ChartValues<DateTimePoint>();
                                                chartValues.Add(new DateTimePoint(nowTime, countValue));
                                                ChartLineRefresh(channelIndex, chartValues);
                                            }
                                            //this.lastTime2 = nowTime;
                                            //}
                                        }
                                    }
                                }
                                break;
                            case 3://加速度传感器
                                   //if ((waveCnt >= 0) && (waveCnt % 3 == 0) && (waveCnt < rasterCount))
                                if (waveCnt == 3)
                                {
                                    for (int rasterID = 0; rasterID < waveCnt / 3; rasterID++)
                                    {
                                        if (entityMap.ContainsKey(rasterID + 1))
                                        {
                                            entityMap.TryGetValue(rasterID + 1, out sensorEntity);
                                            //计算公式： a=(W1-A1)/K
                                            double acceleration1 = CalculateAcceleration(waveLengths[3 * rasterID], Double.Parse(sensorEntity.Param1), Double.Parse(sensorEntity.Param4));
                                            double acceleration2 = CalculateAcceleration(waveLengths[3 * rasterID + 1], Double.Parse(sensorEntity.Param2), Double.Parse(sensorEntity.Param4));
                                            double acceleration3 = CalculateAcceleration(waveLengths[3 * rasterID + 2], Double.Parse(sensorEntity.Param3), Double.Parse(sensorEntity.Param4));
                                            sensorTable.Rows.Add(nowTime, datetime, channelId, sensorEntity.SensorType, waveCnt / 2, rasterID, sensorEntity.ID, sensorEntity.SensorName, waveLengths[3 * rasterID], waveLengths[3 * rasterID + 1], waveLengths[3 * rasterID + 2], 0, acceleration1, acceleration2, acceleration3, 0);
                                            DeviceData deviceData = new DeviceData();
                                            deviceData.deviceId = sensorEntity.ID;
                                            deviceData.deviceType = sensorEntity.SensorType;
                                            deviceData.name = sensorEntity.SensorName;
                                            deviceData.timestamp = nowTime;
                                            deviceData.value = acceleration1;
                                            deviceData.value1 = acceleration2;
                                            deviceData.value2 = acceleration3;
                                            deviceData.wave1 = waveLengths[3 * rasterID];
                                            deviceData.wave2 = waveLengths[3 * rasterID + 1];
                                            deviceData.wave3 = waveLengths[3 * rasterID + 2];
                                            deviceDataList.Add(deviceData);
                                            //if ((nowTime - this.lastTime3) > this.intervalTime)
                                            //{
                                            SensorDeviceData sensorDeviceData = new SensorDeviceData();
                                            sensorDeviceData.collect_datetime = datetime;
                                            sensorDeviceData.collect_time = nowTime;
                                            sensorDeviceData.channel_id = channelId;
                                            sensorDeviceData.sensor_count = waveCnt / 2;
                                            sensorDeviceData.sensor_index = rasterID;
                                            sensorDeviceData.sensor_id = sensorEntity.ID; ;
                                            sensorDeviceData.sensor_type = sensorEntity.SensorType;
                                            sensorDeviceData.sensor_name = sensorEntity.SensorName;
                                            sensorDeviceData.count_value1 = acceleration1;
                                            sensorDeviceData.count_value2 = acceleration2;
                                            sensorDeviceData.count_value3 = acceleration3;
                                            sensorDeviceData.wave_length1 = waveLengths[3 * rasterID];
                                            sensorDeviceData.wave_length2 = waveLengths[3 * rasterID + 1];
                                            sensorDeviceData.wave_length3 = waveLengths[3 * rasterID + 2];
                                            sensorDeviceDataList.Add(sensorDeviceData);

                                            if ((channelId == this.channelIndex) && (rasterID == this.rasterIndex))
                                            {
                                                ChartValues<DateTimePoint> chartValues = new ChartValues<DateTimePoint>();
                                                chartValues.Add(new DateTimePoint(nowTime, acceleration1));
                                                chartValues.Add(new DateTimePoint(nowTime, acceleration2));
                                                chartValues.Add(new DateTimePoint(nowTime, acceleration3));
                                                ChartLineRefresh(channelIndex, chartValues);
                                            }
                                            //this.lastTime3 = nowTime;
                                            //}
                                        }
                                    }
                                }
                                break;
                            case 4://温度传感器
                                for (int rasterID = 0; rasterID < waveCnt; rasterID++)
                                {
                                    if (entityMap.ContainsKey(rasterID + 1))
                                    {
                                        entityMap.TryGetValue(rasterID + 1, out sensorEntity);
                                        //则传感器实时温度：(变量名 – 初始状态波长 )*1000/(转换系数 10pm/℃)+初始温度;
                                        double countValue = (waveLengths[rasterID] - Double.Parse(sensorEntity.Param1)) * 1000 / 10 + Double.Parse(sensorEntity.Param2);
                                        DeviceData deviceData = new DeviceData();
                                        deviceData.deviceId = sensorEntity.ID;
                                        deviceData.deviceType = sensorEntity.SensorType;
                                        deviceData.name = sensorEntity.SensorName;
                                        deviceData.timestamp = nowTime;
                                        deviceData.value = countValue;
                                        deviceData.wave1 = waveLengths[rasterID];
                                        deviceDataList.Add(deviceData);

                                        SensorDeviceData sensorDeviceData = new SensorDeviceData();
                                        sensorDeviceData.collect_datetime = datetime;
                                        sensorDeviceData.collect_time = nowTime;
                                        sensorDeviceData.channel_id = channelId;
                                        sensorDeviceData.sensor_count = waveCnt / 2;
                                        sensorDeviceData.sensor_index = rasterID;
                                        sensorDeviceData.sensor_id = sensorEntity.ID; ;
                                        sensorDeviceData.sensor_type = sensorEntity.SensorType;
                                        sensorDeviceData.sensor_name = sensorEntity.SensorName;
                                        sensorDeviceData.count_value1 = countValue;
                                        sensorDeviceData.wave_length1 = waveLengths[rasterID];
                                        sensorDeviceDataList.Add(sensorDeviceData);

                                        if ((channelId == this.channelIndex) && (rasterID == this.rasterIndex))
                                        {
                                            ChartValues<DateTimePoint> chartValues = new ChartValues<DateTimePoint>();
                                            chartValues.Add(new DateTimePoint(nowTime, countValue));
                                            ChartLineRefresh(channelIndex, chartValues);
                                        }
                                    }
                                }
                                break;
                            case 5://位移传感器
                                if ((waveCnt >= 0) && (waveCnt % 2 == 0) && (waveCnt < rasterCount))
                                {
                                    for (int rasterID = 0; rasterID < waveCnt / 2; rasterID++)
                                    {
                                        if (entityMap.ContainsKey(rasterID + 1))
                                        {
                                            entityMap.TryGetValue(rasterID + 1, out sensorEntity);
                                            //△L=A((λ1-λ2)-(λ10-λ20))²+B((λ1-λ2)-(λ10- λ20))+C
                                            double countValue = CalculateDisplacement(waveLengths[2 * rasterID], waveLengths[2 * rasterID + 1],
                                                Double.Parse(sensorEntity.Param1), Double.Parse(sensorEntity.Param2), Double.Parse(sensorEntity.Param3), Double.Parse(sensorEntity.Param4), Double.Parse(sensorEntity.Param5));
                                            DeviceData deviceData = new DeviceData();
                                            deviceData.deviceId = sensorEntity.ID;
                                            deviceData.deviceType = sensorEntity.SensorType;
                                            deviceData.name = sensorEntity.SensorName;
                                            deviceData.timestamp = nowTime;
                                            deviceData.value = countValue;
                                            deviceData.wave1 = waveLengths[2 * rasterID];
                                            deviceData.wave2 = waveLengths[2 * rasterID + 1];
                                            deviceDataList.Add(deviceData);

                                            SensorDeviceData sensorDeviceData = new SensorDeviceData();
                                            sensorDeviceData.collect_datetime = datetime;
                                            sensorDeviceData.collect_time = nowTime;
                                            sensorDeviceData.channel_id = channelId;
                                            sensorDeviceData.sensor_count = waveCnt / 2;
                                            sensorDeviceData.sensor_index = rasterID;
                                            sensorDeviceData.sensor_id = sensorEntity.ID; ;
                                            sensorDeviceData.sensor_type = sensorEntity.SensorType;
                                            sensorDeviceData.sensor_name = sensorEntity.SensorName;
                                            sensorDeviceData.count_value1 = countValue;
                                            sensorDeviceData.wave_length1 = waveLengths[2 * rasterID];
                                            sensorDeviceData.wave_length2 = waveLengths[2 * rasterID + 1];
                                            sensorDeviceDataList.Add(sensorDeviceData);

                                            if ((channelId == this.channelIndex) && (rasterID == this.rasterIndex))
                                            {
                                                ChartValues<DateTimePoint> chartValues = new ChartValues<DateTimePoint>();
                                                chartValues.Add(new DateTimePoint(nowTime, countValue));
                                                ChartLineRefresh(channelIndex, chartValues);
                                            }
                                        }
                                    }
                                }
                                break;
                            case 6://应力传感器
                            case 7://压力传感器
                            case 8://震动传感器
                            case 9://扭矩传感器
                            case 10://沉降传感器
                                break;
                            default:
                                for (int rasterID = 0; rasterID < waveCnt; rasterID++)
                                {
                                    if ((channelId == this.channelIndex) && (rasterID == this.rasterIndex))
                                    {
                                        ChartValues<DateTimePoint> chartValues = new ChartValues<DateTimePoint>();
                                        chartValues.Add(new DateTimePoint(nowTime, waveLengths[rasterID]));
                                        ChartLineRefresh(channelIndex, chartValues);
                                    }
                                }
                                break;
                        }
                    }
                }
                else
                {
                    for (int rasterID = 0; rasterID < waveCnt; rasterID++)
                    {
                        if ((channelId == this.channelIndex) && (rasterID == this.rasterIndex))
                        {
                            ChartValues<DateTimePoint> chartValues = new ChartValues<DateTimePoint>();
                            chartValues.Add(new DateTimePoint(nowTime, waveLengths[rasterID]));
                            ChartLineRefresh(channelIndex, chartValues);
                        }
                    }
                }
            }

            //发送数据到MQTT服务器
            if (deviceDataList.Count > 0)
            {
                MqttDataPublic(deviceDataList);
                deviceDataList.Clear();
                deviceDataList = null;
            }
            //if (sensorTable.Rows.Count > 0)
            //{
            //    //保存到数据库
            //    saveSensorDataToDBAsync(sensorTable);
            //    sensorTable.Clear();
            //    sensorTable = null;
            //}
            //保存传感器数据到数据库
            if (sensorDeviceDataList.Count > 0)
            {
                //保存到Mysql数据库
                if (isSaveDataToMysql)
                {
                    SaveSensorDeviceDataToMysql(sensorDeviceDataList);
                }
                //保存到Txt或者Excel文件
                if (isSaveWaveToExcel)
                {
                    //SaveWaveDataToTxt(sensorDeviceDataList);
                    //SaveWaveDataToExcel(sensorDeviceDataList);
                }
                sensorDeviceDataList.Clear();
                sensorDeviceDataList = null;
            }
        }

        /// <summary>
        /// 连续折现图的方法
        /// </summary>
        //private void StackedAreaSeriesRefresh()
        //{
        //    long nowTime = new DateTimeOffset(DateTime.UtcNow).ToUnixTimeMilliseconds();
        //    string datetime = (new DateTime(1970, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc).AddMilliseconds((long)nowTime).ToLocalTime()).ToString("yyyy-MM-dd HH:mm:ss");
        //    //if ((nowTime - this.lastTime1) < this.intervalTime)
        //    //{
        //    //    return;
        //    //}
        //    this.xTimes++;

        //    DataTable rasterTable = new DataTable();
        //    rasterTable.Columns.Add("collect_time", typeof(long));
        //    rasterTable.Columns.Add("collect_datetime", typeof(string));
        //    rasterTable.Columns.Add("channel_id", typeof(int));
        //    rasterTable.Columns.Add("raster_count", typeof(int));
        //    rasterTable.Columns.Add("wave_length1", typeof(double));
        //    rasterTable.Columns.Add("wave_length2", typeof(double));
        //    rasterTable.Columns.Add("wave_length3", typeof(double));
        //    rasterTable.Columns.Add("wave_length4", typeof(double));
        //    rasterTable.Columns.Add("wave_length5", typeof(double));
        //    rasterTable.Columns.Add("wave_length6", typeof(double));
        //    rasterTable.Columns.Add("wave_length7", typeof(double));
        //    rasterTable.Columns.Add("wave_length8", typeof(double));
        //    rasterTable.Columns.Add("wave_length9", typeof(double));
        //    rasterTable.Columns.Add("wave_length10", typeof(double));
        //    rasterTable.Columns.Add("wave_length11", typeof(double));
        //    rasterTable.Columns.Add("wave_length12", typeof(double));
        //    rasterTable.Columns.Add("wave_length13", typeof(double));
        //    rasterTable.Columns.Add("wave_length14", typeof(double));
        //    rasterTable.Columns.Add("wave_length15", typeof(double));
        //    rasterTable.Columns.Add("wave_length16", typeof(double));

        //    DataTable sensorTable = new DataTable();
        //    sensorTable.Columns.Add("collect_time", typeof(long));
        //    sensorTable.Columns.Add("collect_datetime", typeof(string));
        //    sensorTable.Columns.Add("channel_id", typeof(int));
        //    sensorTable.Columns.Add("sensor_type", typeof(int));
        //    sensorTable.Columns.Add("sensor_count", typeof(int));
        //    sensorTable.Columns.Add("sensor_index", typeof(int));
        //    sensorTable.Columns.Add("sensor_id", typeof(int));
        //    sensorTable.Columns.Add("sensor_name", typeof(string));
        //    sensorTable.Columns.Add("wave_length1", typeof(double));
        //    sensorTable.Columns.Add("wave_length2", typeof(double));
        //    sensorTable.Columns.Add("wave_length3", typeof(double));
        //    sensorTable.Columns.Add("wave_length4", typeof(double));
        //    sensorTable.Columns.Add("count_value1", typeof(double));
        //    sensorTable.Columns.Add("count_value2", typeof(double));
        //    sensorTable.Columns.Add("count_value3", typeof(double));
        //    sensorTable.Columns.Add("count_value4", typeof(double));

        //    List<DeviceData> deviceDataList = new List<DeviceData>();
        //    List<SensorDeviceData> sensorDeviceDataList = new List<SensorDeviceData>();
        //    string[] values = new string[rasterCount + 2];

        //    for (int channelId = 0; channelId < this.channelCount; channelId++)
        //    {
        //        if (channelId == this.channelIndex)
        //        {
        //            values[0] = 1 + channelId + "";
        //            values[1] = 2 + "";
        //            //更新纵坐标数据
        //            double waveLength1 = Math.Round(R.NextDouble() + Page5.getS1A1(), 4);
        //            double waveLength2 = Math.Round(R.NextDouble() + Page5.getS1A2(), 4);
        //            double stressValue1 = CalculateStress(waveLength1, waveLength2, Page5.getS1A1(), Page5.getS1A2(), Page5.getS1K1(), Page5.getS1K2(), Page5.getS1K3());

        //            values[2] = waveLength1 + "";
        //            values[3] = waveLength2 + "";

        //            double waveLength3 = Math.Round(R.NextDouble() + Page5.getS2A1(), 4);
        //            double waveLength4 = Math.Round(R.NextDouble() + Page5.getS2A2(), 4);
        //            double stressValue2 = CalculateStress(waveLength3, waveLength4, Page5.getS2A1(), Page5.getS2A2(), Page5.getS2K1(), Page5.getS2K2(), Page5.getS2K3());

        //            values[4] = waveLength3 + "";
        //            values[5] = waveLength4 + "";

        //            double waveLength5 = Math.Round(R.NextDouble() + Page5.getS1A1(), 4);
        //            double waveLength6 = Math.Round(R.NextDouble() + Page5.getS1A2(), 4);
        //            double stressValue3 = CalculateStress(waveLength1, waveLength2, Page5.getS1A1(), Page5.getS1A2(), Page5.getS1K1(), Page5.getS1K2(), Page5.getS1K3());

        //            values[6] = waveLength5 + "";
        //            values[7] = waveLength6 + "";

        //            rasterTable.Rows.Add(nowTime, datetime, channelId, 6, waveLength1, waveLength2, waveLength3, waveLength4, waveLength5, waveLength6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
        //            sensorTable.Rows.Add(nowTime, datetime, channelId, 1, 1, 1, 1, "测试传感器", waveLength1, waveLength2, waveLength3, waveLength4, stressValue1, stressValue2, stressValue3, 0);
        //            //double axialForce = Math.Round(Math.Abs(((stressValue1 + stressValue2) * Page5.getEM1() * Page5.getPE()) / (Page5.getPI() * 32 * 32)) + Page5.getAF1(), 4);
        //            //if (axialForce > Page5.getAxialForceExceeds())
        //            //{
        //            //    axialAlarmRepeatTimes++;
        //            //    if (Page5.getIsAlarmNotify())
        //            //    {
        //            //        if (axialAlarmRepeatTimes > Page5.getRepeatTimes())
        //            //        {
        //            //            if (Page5.getIsAlarmEmail())
        //            //            {
        //            //                SendEmail("smtp.qq.com", 587, "24139297@qq.com", "rvsdsfqwexwrbgba", Page5.getAlarmEmail(), "告警通知", "通道：" + channelId + " 轴力值：" + axialForce + " 连续 " + axialAlarmRepeatTimes + " 次" + "超过警告阈值：" + Page5.getAxialForceExceeds() + "，请注意！");
        //            //            }
        //            //            if (Page5.getIsAlarmPhone())
        //            //            {
        //            //                int roundedValue = Convert.ToInt32(axialForce);
        //            //                string[] templateParamSet = [channelId + "", roundedValue + "", axialAlarmRepeatTimes + ""];
        //            //                SendSms(Page5.getAlarmPhone(), templateParamSet);
        //            //            }
        //            //            axialAlarmRepeatTimes = 0;
        //            //        }
        //            //    }
        //            //}

        //            ShowTableViewData(values, channelId);
        //            values = null;

        //            ChartValues<DateTimePoint> chartValues = new ChartValues<DateTimePoint>();
        //            chartValues.Add(new DateTimePoint(nowTime, stressValue1));
        //            chartValues.Add(new DateTimePoint(nowTime, stressValue2));
        //            chartValues.Add(new DateTimePoint(nowTime, stressValue3));
        //            ChartLineRefresh(channelId, chartValues);

        //            SensorDeviceData sensorDeviceData = new SensorDeviceData();
        //            sensorDeviceData.collect_datetime = datetime;
        //            sensorDeviceData.collect_time = nowTime;
        //            sensorDeviceData.channel_id = channelId;
        //            sensorDeviceData.sensor_type = 1;
        //            sensorDeviceData.sensor_count = 1;
        //            sensorDeviceData.sensor_index = 1;
        //            sensorDeviceData.sensor_id = 1;
        //            sensorDeviceData.sensor_name = "测试传感器";
        //            sensorDeviceData.count_value1 = stressValue1;
        //            sensorDeviceData.count_value2 = stressValue2;
        //            sensorDeviceData.count_value3 = stressValue3;
        //            sensorDeviceData.wave_length1 = waveLength1;
        //            sensorDeviceData.wave_length2 = waveLength2;
        //            sensorDeviceData.wave_length3 = waveLength3;
        //            sensorDeviceDataList.Add(sensorDeviceData);
        //        }
        //    }
        //    RefreshTableViewData();

        //    //保存到Mysql文件
        //    if (sensorDeviceDataList.Count > 0)
        //    {
        //        //SaveWaveDataToTxt(sensorWaveDataList);
        //        //SaveWaveDataToExcel(sensorWaveDataList);
        //        sensorDeviceDataList.Clear();
        //        sensorDeviceDataList = null;
        //    }
        //    //保存波形数据到数据库
        //    if (rasterTable.Rows.Count > 0)
        //    {
        //        //保存到数据库
        //        //saveRasterWaveToDBAsync(rasterTable);
        //        rasterTable.Clear();
        //        rasterTable = null;
        //    }
        //    //保存传感器数据到数据库
        //    if (sensorTable.Rows.Count > 0)
        //    {
        //        //保存到数据库
        //        //saveSensorDataToDBAsync(sensorTable);
        //        sensorTable.Clear();
        //        sensorTable = null;
        //    }
        //}

        private void ChartLineRefresh(int channelIndex, ChartValues<DateTimePoint> chartValues)
        {
            try
            {
                if (OscChart.Series.Count < chartValues.Count)
                {
                    InitChartConfig(channelIndex, chartValues.Count);
                }
                // 假设你在非UI线程上
                if (OscChart.InvokeRequired)
                {
                    OscChart.Invoke(new System.Action(() =>
                    {
                        for (int index = 0; index < chartValues.Count; index++)
                        {
                            //添加y值，chartValues为波长1数据
                            OscChart.Series[index].Values.Add(chartValues[index]);
                            int _count = OscChart.Series[index].Values.Count;
                            if (_count > this.xCount)
                            {
                                //只关心前面30个数据
                                OscChart.Series[index].Values.RemoveAt(0);
                            }
                        }
                        //在这里进行UI相关的操作，例如修改OscChart的属性等
                        //OscChart.AxisX[0].MaxValue = this.xTimes;
                        //OscChart.AxisX[0].MinValue = this.xTimes - this.xCount;
                        OscChart.Refresh();
                    }));
                }
                else
                {
                    for (int index = 0; index < chartValues.Count; index++)
                    {
                        //添加y值，chartValues为波长1数据
                        OscChart.Series[index].Values.Add(chartValues[index]);
                        int _count = OscChart.Series[index].Values.Count;
                        if (_count > this.xCount)
                        {
                            //只关心前面30个数据
                            OscChart.Series[index].Values.RemoveAt(0);
                        }
                    }
                    // 直接进行操作，因为当前线程就是UI线程
                    //OscChart.AxisX[0].MaxValue = this.xTimes;
                    //OscChart.AxisX[0].MinValue = this.xTimes - this.xCount;
                    OscChart.Refresh();

                }
            }
            catch (Exception ex)
            {
                log.Error(ex.Message);
            }
            finally
            {
            }
        }

        private void InitChartConfig()
        {
            string title = "值";
            try
            {
                if (OscChart.Series.Count > 0)
                {
                    // 假设你在非UI线程上
                    if (OscChart.InvokeRequired)
                    {
                        OscChart.Invoke(new System.Action(() =>
                        {

                            OscChart.Series.Clear();
                            OscChart.AxisX.Clear();
                            OscChart.AxisY.Clear();
                        }));
                    }
                    else
                    {
                        OscChart.Series.Clear();
                        OscChart.AxisX.Clear();
                        OscChart.AxisY.Clear();
                    }
                }
                if (OscChart.InvokeRequired)
                {
                    OscChart.Invoke(new System.Action(() =>
                    {
                        OscChart.Series.Add(new LiveCharts.Wpf.StackedAreaSeries
                        {
                            Title = title,
                            PointGeometry = DefaultGeometries.Circle,
                            PointGeometrySize = 15,
                            StrokeThickness = 4,
                            LineSmoothness = 1,
                            PointForeground = System.Windows.Media.Brushes.Blue,
                            Values = InitChartValuesEmptyData(),
                            ScalesYAt = 0
                        });
                        OscChart.AxisY.Add(new LiveCharts.Wpf.Axis
                        {
                            Title = title,
                            FontSize = 12,
                            Foreground = System.Windows.Media.Brushes.DodgerBlue,
                            Position = AxisPosition.LeftBottom
                        });
                        OscChart.AxisX.Add(new LiveCharts.Wpf.Axis
                        {
                            //Title = "时间",
                            FontSize = 12,
                            DisableAnimations = true,
                            Foreground = System.Windows.Media.Brushes.Black,
                            //LabelFormatter = value => value.ToString(),
                            //LabelFormatter = value => new System.DateTime(System.DateTime.Now.Ticks - (long)(this.xNumber - (long)value) * this.intervalTime * 10000).ToString("mm:ss"),
                            LabelFormatter = value => (new DateTime(1970, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc).AddMilliseconds((long)value).ToLocalTime()).ToString("HH:mm:ss"),
                            //Separator = new Separator
                            //{
                            //    Step = 1,
                            //    IsEnabled = true
                            //},
                            //MaxValue = this.xTimes,
                            //MinValue = this.xTimes - this.xCount
                        });
                    }));
                }
                else
                {
                    OscChart.Series.Add(new LiveCharts.Wpf.StackedAreaSeries
                    {
                        Title = title,
                        PointGeometry = DefaultGeometries.Circle,
                        PointGeometrySize = 15,
                        StrokeThickness = 4,
                        LineSmoothness = 1,
                        PointForeground = System.Windows.Media.Brushes.Blue,
                        Values = InitChartValuesEmptyData(),
                        ScalesYAt = 0
                    });
                    OscChart.AxisY.Add(new LiveCharts.Wpf.Axis
                    {
                        Title = title,
                        FontSize = 12,
                        Foreground = System.Windows.Media.Brushes.DodgerBlue,
                        Position = AxisPosition.LeftBottom
                    });
                    OscChart.AxisX.Add(new LiveCharts.Wpf.Axis
                    {
                        //Title = "时间",
                        FontSize = 12,
                        DisableAnimations = true,
                        Foreground = System.Windows.Media.Brushes.Black,
                        //LabelFormatter = value => value.ToString(),
                        //LabelFormatter = value => new System.DateTime(System.DateTime.Now.Ticks - (long)(this.xNumber - (long)value) * this.intervalTime * 10000).ToString("mm:ss"),
                        LabelFormatter = value => (new DateTime(1970, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc).AddMilliseconds((long)value).ToLocalTime()).ToString("HH:mm:ss"),
                        //Separator = new Separator
                        //{
                        //    Step = 1,
                        //    IsEnabled = true
                        //},
                        //MaxValue = this.xTimes,
                        //MinValue = this.xTimes - this.xCount
                    });
                }
            }
            catch (Exception ex)
            {
                log.Error(ex.Message);
            }
            finally
            {
            }
        }

        private void InitChartConfig(int channelID, int yIndex)
        {
            //string waveDictionary = "波长";
            try
            {
                if (OscChart.Series.Count > 0)
                {
                    // 假设你在非UI线程上
                    if (OscChart.InvokeRequired)
                    {
                        OscChart.Invoke(new System.Action(() =>
                        {
                            OscChart.Series.Clear();
                            OscChart.AxisX.Clear();
                            OscChart.AxisY.Clear();
                        }));
                    }
                    else
                    {
                        OscChart.Series.Clear();
                        OscChart.AxisX.Clear();
                        OscChart.AxisY.Clear();
                    }
                }
                if (OscChart.InvokeRequired)
                {
                    OscChart.Invoke(new System.Action(() =>
                    {
                        for (int y = 1; y <= yIndex; y++)
                        {
                            string title = "通道-" + (channelID + 1) + "-传感器-" + y;
                            OscChart.Series.Add(new LiveCharts.Wpf.StackedAreaSeries
                            {
                                Title = title,
                                PointGeometry = DefaultGeometries.Circle,
                                PointGeometrySize = 15,
                                StrokeThickness = 4,
                                LineSmoothness = 1,
                                PointForeground = System.Windows.Media.Brushes.Blue,
                                Values = InitChartValuesEmptyData(),
                                ScalesYAt = 0
                            });
                        }
                        OscChart.AxisY.Add(new LiveCharts.Wpf.Axis
                        {
                            Title = "值",
                            FontSize = 12,
                            Foreground = System.Windows.Media.Brushes.DodgerBlue,
                            Position = AxisPosition.LeftBottom
                        });
                        OscChart.AxisX.Add(new LiveCharts.Wpf.Axis
                        {
                            //Title = "时间",
                            FontSize = 12,
                            DisableAnimations = true,
                            Foreground = System.Windows.Media.Brushes.Black,
                            //LabelFormatter = value => value.ToString(),
                            //LabelFormatter = value => new System.DateTime(System.DateTime.Now.Ticks - (long)(this.xNumber - (long)value) * this.intervalTime * 10000).ToString("mm:ss"),
                            LabelFormatter = value => (new DateTime(1970, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc).AddMilliseconds((long)value).ToLocalTime()).ToString("HH:mm:ss"),
                            //Separator = new Separator
                            //{
                            //    Step = 1,
                            //    IsEnabled = true
                            //},
                            //MaxValue = this.xTimes,
                            //MinValue = this.xTimes - this.xCount
                        });
                    }));
                }
                else
                {
                    for (int y = 0; y < yIndex; y++)
                    {
                        string title = "通道-" + (channelID + 1) + "-传感器-" + (y + 1);
                        OscChart.Series.Add(new LiveCharts.Wpf.StackedAreaSeries
                        {
                            Title = title,
                            PointGeometry = DefaultGeometries.Circle,
                            PointGeometrySize = 15,
                            StrokeThickness = 4,
                            LineSmoothness = 1,
                            PointForeground = System.Windows.Media.Brushes.Blue,
                            Values = InitChartValuesEmptyData(),
                            ScalesYAt = 0
                        });
                    }
                    OscChart.AxisY.Add(new LiveCharts.Wpf.Axis
                    {
                        Title = "值",
                        FontSize = 12,
                        Foreground = System.Windows.Media.Brushes.DodgerBlue,
                        Position = AxisPosition.LeftBottom
                    });
                    OscChart.AxisX.Add(new LiveCharts.Wpf.Axis
                    {
                        //Title = "时间",
                        FontSize = 12,
                        DisableAnimations = true,
                        Foreground = System.Windows.Media.Brushes.Black,
                        //LabelFormatter = value => value.ToString(),
                        //LabelFormatter = value => new System.DateTime(System.DateTime.Now.Ticks - (long)(this.xNumber - (long)value) * this.intervalTime * 10000).ToString("mm:ss"),
                        LabelFormatter = value => (new DateTime(1970, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc).AddMilliseconds((long)value).ToLocalTime()).ToString("HH:mm:ss"),
                        //Separator = new Separator
                        //{
                        //    Step = 1,
                        //    IsEnabled = true
                        //},
                        //MaxValue = this.xTimes,
                        //MinValue = this.xTimes - this.xCount
                    });
                }
            }
            catch (Exception ex)
            {
                log.Error(ex.Message);
            }
            finally
            {
            }
        }

        private static ChartValues<DateTimePoint> InitChartValuesEmptyData()
        {
            ChartValues<DateTimePoint> chartValues = new ChartValues<DateTimePoint>();
            return chartValues;
        }


        // 接收发送给本机IP对应端口号的数据报
        private void ReceiveMessage()
        {
            try
            {
                while (MainForm.getOpenServerPort())
                {
                    //用来保存发送方的IP和端口号
                    EndPoint point = new IPEndPoint(IPAddress.Any, 0);
                    //消息缓存区申请
                    byte[] buffer = new byte[1024];
                    Socket serverSocket = MainForm.getServerSocket();
                    if (serverSocket != null)
                    {
                        //接收数据报
                        int length = serverSocket.ReceiveFrom(buffer, ref point);
                        byte[] revBuf = new byte[length];
                        Buffer.BlockCopy(buffer, 0, revBuf, 0, length);
                        //显示在波形图里
                        this.ReceiveWaveDataOPM(revBuf);
                        revBuf = null;
                    }
                    buffer = null;

                }
            }
            catch (SocketException ex)
            {
				//MessageBox.Show("接收发送给本机IP对应端口号的数据报错！" + e.Message, "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
                log.Error("接收发送给本机IP对应端口号的数据报错！" + ex.Message);
                log.Error(ex.Message);
            }
            finally
            {
                //if (serverSocket != null)
                //{
                //    if (serverSocket.Connected)
                //    {
                //        serverSocket.Disconnect(false);
                //    }
                //    serverSocket.Close();
                //    serverSocket.Dispose();
                //}
            }
        }

        //OPM-T1622F 光栅解调仪设备通信协议解析
        private void ReceiveWaveDataOPM(byte[] revData)
        {
            long nowTime = DateTimeOffset.Now.ToUnixTimeMilliseconds();
            string datetime = (new DateTime(1970, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc).AddMilliseconds((long)nowTime).ToLocalTime()).ToString("yyyy-MM-dd HH:mm:ss");
            log.Debug("ReceiveWaveDataOPM start timestamp = " + nowTime);
            //if ((nowTime - this.lastTime) < this.intervalTime)
            //{
            //    return;
            //}
            //this.lastTime = nowTime;

            this.xTimes++;

            if (this.xTimes >= long.MaxValue - 1000)
            {
                this.xTimes = this.xCount;
            }
            if ((this.isWaveCollectTimes) && (this.xTimes > this.waveCollectTimes))
            {
                //UI显示
                this.btnCollectWave.Text = "开始采集";
                this.btnCollectWave.Enabled = true;
                this.tbWaveFrequency.Enabled = true;
                this.tbWaveCollectTimes.Enabled = true;
                this.cbWaveCollectTimes.Enabled = true;
                this.tbWaveFilePath.Enabled = true;
                this.ibOpenFilePath.Enabled = true;
                this.cbSaveWaveExcel.Enabled = true;

                Socket serverSocket = MainForm.getServerSocket();
                if (serverSocket == null)
                {
                    return;
                }
                try
                {
                    EndPoint endPoint = MainForm.getEndPoint();
                    byte[] bmsg = [0x01, 0x0A, 0x00];

                    //发送数据包
                    serverSocket.SendTo(bmsg, endPoint);

                    //先关闭线程，再关闭服务器
                    //if (receiveThread1 != null){
                    //    receiveThread1.Interrupt();
                    //}
                }
                catch (SocketException ex)
                {
                    MessageBox.Show("发送数据报时出现异常：" + ex.ErrorCode + "！", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
                    log.Error(ex.Message);
                }
                finally
                {

                }
                return;
            }


            int index = 0;
            byte head = revData[index++];
            byte cmd = revData[index++];

            if (cmd == 0x02)
            {

            }
            else if (cmd == 0x04)
            {

            }
            else if (cmd == 0x06)
            {

            }
            else if (cmd == 0x07)
            {

            }
            else if (cmd == 0x08)
            {

            }
            else if (cmd == 0x0A)
            {

            }
            else if (cmd == 0x0C)
            {
                try
                {
                    List<SensorWaveData> sensorWaveDataList = new List< SensorWaveData>();
                    for (int channelId = 0; channelId < channelCount; channelId++)
                    {
                        index++;
                        byte waveCnt = revData[index++];
                        if ((waveCnt > 0)&&(waveCnt <= 16))
                        {
                            byte[] tempArray = new byte[2 * waveCnt];
                            Array.Copy(revData, index, tempArray, 0, 2 * waveCnt);
                            string[] waveValues = new string[rasterCount + 2];
                            waveValues[0] = channelId + 1 + "";
                            waveValues[1] = waveCnt + "";
							double[] waveLengths = new double[16];
                            SensorWaveData sensorWaveData = new SensorWaveData();
                            sensorWaveData.timestamp = nowTime;
                            sensorWaveData.channelId = channelId + 1;
                            sensorWaveData.waveCnt = waveCnt;
                            for (byte rasterID = 0; rasterID < waveCnt; rasterID++)
                            {
                                byte[] tempArray1 = new byte[2];
                                Array.Copy(tempArray, 2 * rasterID, tempArray1, 0, 2);

                                uint valueL = tempArray1[0];
                                uint valueH = tempArray1[1];
                                double waveLength = (double)DivideAndRound((valueL + valueH * 256), 1000, 5) + 1520;
                                waveValues[rasterID + 2] = waveLength + "";
                                waveLengths[rasterID] = waveLength;
                            }
                            tempArray = null;
                            //显示到数据栏
                            ShowTableViewData(waveValues, channelId);
                            waveValues = null;
                            sensorWaveData.waveLengths = waveLengths;
                            sensorWaveDataList.Add(sensorWaveData);
                            waveLengths = null;
                        }
                        index = index + 2 * waveCnt;
                        if (index >= revData.Length)
                        {
                            break;
                        }
                    }
                    if (sensorWaveDataList.Count > 0)
                    {
                        // 生产者线程
                        Task producer = Task.Run(() =>
                        {
                            queue.Enqueue(sensorWaveDataList);
                            //Console.WriteLine($"Enqueued: {sensorWaveDataList}");
                        });
                        //保存到TXT文件
                        //SaveWaveDataToTxt(sensorWaveDataList);
                        //sensorWaveDataList.Clear();
                        //sensorWaveDataList = null;
                    }
                    RefreshTableViewData();
                }
                catch (SocketException ex)
                {
                    //MessageBox.Show("发送数据报时出现异常：" + es.ErrorCode + "！", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
                    log.Error(ex.Message);
                }
                finally
                {

                }
            }
            else if (cmd == 0x14)
            {

            }
            else if (cmd == 0x16)
            {

            }
            else if (cmd == 0x17)
            {

            }
            else if (cmd == 0x24)
            {

            }
            else if (cmd == 0x26)
            {

            }
            else if (cmd == 0x2E)
            {

            }
            else if (cmd == 0x30)
            {

            }
            else if (cmd == 0x32)
            {

            }
            else if (cmd == 0x34)
            {

            }
            else
            {
            }
            long endTime = DateTimeOffset.Now.ToUnixTimeMilliseconds();
            log.Debug("ReceiveWaveDataOPM end timestamp = " + endTime);
        }

        //private async Task saveRasterWaveToDBAsync(DataTable table)
        //{
        //    await MainForm.db.BulkCopyAsync(table, rasterTableName, timeoutSeconds, notifyAfter, callBack, cancellationToken);
        //}

        private async Task saveSensorDataToDBAsync(DataTable table)
        {
            await MainForm.db.BulkCopyAsync(table, sensorTableName, timeoutSeconds, notifyAfter, callBack, cancellationToken);
        }
        
        public static decimal DivideAndRound(decimal dividend, decimal divisor, int decimalPlaces)
        {
            if (divisor == 0)
            {
                throw new DivideByZeroException();
            }
            decimal result = dividend / divisor;
            return Math.Round(result, decimalPlaces);
        }

        //应变计算公式：ε＝[（W1－A1）- ((W2－A2)/ K2) * K3] /K1
        //其中：W1 为应变光栅当前测量波长，A1 为应变光栅安装完成后初始波长
        // W2 为温度光栅当前测量波长，A2 为温度光栅安装完成后初始波长
        // K1 为应变系数， K2 为温度光栅温度系数，K3 为应变光栅温度系数
        private static double CalculateStress(double W1, double W2, double A1, double A2, double K1, double K2, double K3)
        {
            double stress = (((W1 - A1) - ((W2 - A2) / K2) * K3) / K1) * 1000;

            return Math.Round(stress, 4);
        }

        //计算公式：A =[(Wa - Wa0)-(Wb-Wb0)]/k
        //其中：	Wa—a光栅测试波长(小波长)         Wa0—a光栅零点波长
        //          Wb—b光栅测试波长(大波长）        Wb0—b光栅零点波长
        //备注：初始波长不能以报告的初始波长，安装的时候要以当前环境读出来的波长为初始波长
        private static double CalculateAngle(double Wa, double Wa0, double Wb, double Wb0, double K)
        {
            double stress = ((Wa - Wa0) - (Wb - Wb0)) / K;

            return Math.Round(stress, 4);
        }

        //公式：加速度A =（W1－A1）/K
        //A为加速度，W1是测试波长，A1是原始波长，K是加速度灵敏度
        private static double CalculateAcceleration(double W1, double A1, double K)
        {
            double stress = ((W1 - A1) / K) * 1000;

            return Math.Round(stress, 4);
        }

        //位移计算公式：△L=A((λ1-λ2)-(λ10-λ20))²+B((λ1-λ2)-(λ10- λ20))+C
        // 上式中：A,B,C 为多项式系数
        // △L 为仪器长度变化量，单位 mm
        // λ1、λ2 为当前光栅的波长，单位 nm
        // λ10、λ20 为初始光栅的波长(必须用“计算参数”两光栅波长),单位 nm
        private static double CalculateDisplacement(double λ1, double λ2, double λ10, double λ20, double A, double B, double C)
        {
            double stress = A * Math.Pow(((λ1 - λ2) - (λ10 - λ20)), 2) + B * ((λ1 - λ2) - (λ10 - λ20)) + C;

            return Math.Round(stress, 4);
        }

        private void CreateExcelDataFile()
        {
            if (!this.isSaveWaveToExcel)
            {
                return;
            }
            // 创建Excel应用程序实例
            //if (excelApp == null)
            //{
            //    MessageBox.Show("无法创建excel对象，请确认excel环境是否正常");
            //    return;
            //}
            this.excelApp = new Excel.Application();
            this.excelApp.Visible = false;
            this.excelApp.UserControl = true;
            this.excelApp.DisplayAlerts = false;
            Excel.Workbooks workbooks = this.excelApp.Workbooks;
            try
            {
                DateTime dt = DateTime.Now;
                //int hour = dt.Hour;
                //int min = dt.Minute;
                //int hh = hour * 60 + min / 1;
                string date = dt.Year.ToString("D4") + dt.Month.ToString("D2") + dt.Day.ToString("D2");
                string filePath;
                if (waveFilePath == "")
                {
                    filePath = AppDomain.CurrentDomain.BaseDirectory + waveFileName + @"-" + date + @".xlsx";
                }
                else
                {
                    filePath = waveFilePath + waveFileName + @"-" + date + @".xlsx";
                }

                if (!File.Exists(filePath))
                {
                    File.Copy(AppDomain.CurrentDomain.BaseDirectory + waveFileName + @".xlsx", filePath, true);
                }
                this.workbook = workbooks.Add(filePath); //加载模板
                waveFileNameDate = date;
            }
            catch (Exception ex)
            {
                bool isUnlocked = FileUnlocker.UnlockFile(filePath);
                if (isUnlocked)
                {
                    this.workbook = workbooks.Add(filePath); //加载模板
                }
                else
                {
                    MessageBox.Show("存储 Excel 文件时出错,文件可能正被打开！\n" + ex.Message);
                    log.Error(ex.Message);
                    return;
                }
            }
        }

        private void ReadExcelDataFile()
        {
            // 创建Excel应用程序实例
            this.excelApp = new Excel.Application();
            if (this.excelApp == null)
            {
                MessageBox.Show("无法创建excel对象，请确认excel环境是否正常");
                return;

            }
            this.excelApp.Visible = false;
            this.excelApp.UserControl = true;
            this.excelApp.DisplayAlerts = false;
            Excel.Workbooks workbooks = this.excelApp.Workbooks;
            try
            {
                DateTime dt = DateTime.Today; // 获取今天的日期
                //DateTime yesterday = dt.AddDays(-1); // 获取前一天的日期

                string date = dt.Year.ToString("D4") + dt.Month.ToString("D2") + dt.Day.ToString("D2");
                string filePath;
                if (waveFilePath == "")
                {
                    filePath = AppDomain.CurrentDomain.BaseDirectory + waveFileName + @"-" + date + @".xlsx";
                }
                else
                {
                    filePath = waveFilePath + waveFileName + @"-" + date + @".xlsx";
                }

                if (File.Exists(filePath))
                {
                    this.workbook = workbooks.Add(filePath); //加载模板
                }
                else
                {
                    File.Copy(AppDomain.CurrentDomain.BaseDirectory + waveFileName + @".xlsx", filePath, true);
                    this.workbook = workbooks.Add(filePath); //加载模板
                }
            }
            catch (Exception ex)
            {
                bool isUnlocked = FileUnlocker.UnlockFile(filePath);
                if (isUnlocked)
                {
                    this.workbook = workbooks.Add(filePath); //加载模板
                }
                else
                {
                    MessageBox.Show("存储 Excel 文件时出错,文件可能正被打开！\n" + ex.Message);
                    log.Error(ex.Message);
                    return;
                }
            }
        }
        //数据保存到excel
        public void ShowTableViewData(string[] waveValues, int channelID)
        {
            ColumnData columnData = dataList[channelID];
            columnData.Time = DateTime.Now.ToString();
            columnData.ChannelNumber = waveValues[0];
            columnData.WaveNumber = waveValues[1];
            columnData.Sensor1 = waveValues[2];
            columnData.Sensor2 = waveValues[3];
            columnData.Sensor3 = waveValues[4];
            columnData.Sensor4 = waveValues[5];
            columnData.Sensor5 = waveValues[6];
            columnData.Sensor6 = waveValues[7];
            columnData.Sensor7 = waveValues[8];
            columnData.Sensor8 = waveValues[9];
            columnData.Sensor9 = waveValues[10];
            columnData.Sensor10 = waveValues[11];
            columnData.Sensor11 = waveValues[12];
            columnData.Sensor12 = waveValues[13];
            columnData.Sensor13 = waveValues[14];
            columnData.Sensor14 = waveValues[15];
            columnData.Sensor15 = waveValues[16];
            columnData.Sensor16 = waveValues[17];
        }

        public void RefreshTableViewData()
        {
            try
            {
                if (uiDataGridView1.InvokeRequired)
                {
                    uiDataGridView1.Invoke(new System.Action(() =>
                    {
                        // 在这里安全地修改uiDataGri
                        uiDataGridView1.DataSource = dataList;
                        uiDataGridView1.Refresh();
                    }));
                }
                else
                {
                    // 直接修改，但通常不推荐，因为即使在当前线程，也应该使用Invoke来保持一致性和避免潜在问题
                    uiDataGridView1.DataSource = dataList;
                    uiDataGridView1.Refresh();
                }
            }
            catch (Exception ex)
            {
                log.Error(ex.Message);
            }
        }

        public async Task SaveWaveDataToTxt(List<SensorDeviceData> sensorDeviceDatas)
        {
            try {
                if (this.sw == null)
                {
                    //CreateTxtDataFile();
                    DateTime dt = DateTime.Now;
                    string date = dt.Year.ToString("D4") + dt.Month.ToString("D2") + dt.Day.ToString("D2");
                    if (waveFilePath == "")
                    {
                        filePath = AppDomain.CurrentDomain.BaseDirectory + waveFileName + @"-" + date + @".txt";
                    }
                    else
                    {
                        filePath = waveFilePath + waveFileName + @"-" + date + @".txt";
                    }
                    sw = File.AppendText(filePath);
                    waveFileNameDate = date;
                }
                else
                {
                    DateTime dt = DateTime.Now;
                    string date = dt.Year.ToString("D4") + dt.Month.ToString("D2") + dt.Day.ToString("D2");
                    if (!waveFileNameDate.Equals(date))
                    {
                        sw.Close();
                        sw.Dispose();
                        sw = null;
                        if (waveFilePath == "")
                        {
                            filePath = AppDomain.CurrentDomain.BaseDirectory + waveFileName + @"-" + date + @".txt";
                        }
                        else
                        {
                            filePath = waveFilePath + waveFileName + @"-" + date + @".txt";
                        }
                        sw = File.AppendText(filePath);
                        waveFileNameDate = date;
                    }
                }
                if (this.sw != null)
                {
                    foreach (SensorDeviceData sensorDeviceData in sensorDeviceDatas)
                    {
                        sw.WriteLine(sensorDeviceData.ToString()); // 写入文本。
                    }
                    sw.Flush();
                }
            }
            catch(Exception ex)
            {
                log.Error(ex.Message);
            }
        }

        //数据保存到excel
        public async Task SaveWaveDataToExcel(List<SensorDeviceData> sensorDeviceDatas)
        {
            if (!this.isSaveWaveToExcel)
            {
                return;
            }
            if (this.excelApp == null)
            {
                CreateExcelDataFile();
            }
            if (this.workbook == null)
            {
                MessageBox.Show("无法打开 Workbook 对象，请确认 Excel 文件是否正常");
                return;

            }
            try
            {
                DateTime dt = DateTime.Now;
                int hour = dt.Hour;
                int min = dt.Minute;
                int sec = dt.Second;
                int msec = dt.Millisecond;
                string date = dt.Year.ToString("D4") + dt.Month.ToString("D2") + dt.Day.ToString("D2");
                string filePath;
                if (waveFilePath == "")
                {
                    filePath = AppDomain.CurrentDomain.BaseDirectory + waveFileName + @"-" + date + @".xlsx";
                }
                else
                {
                    filePath = waveFilePath + waveFileName + @"-" + date + @".xlsx";
                }
                if (!waveFileNameDate.Equals(date))
                {
                    this.workbook.Close(false);
                    this.workbook = null;
                    //excelApp.Quit();
                    //excelApp = null;
                    Excel.Workbooks workbooks = this.excelApp.Workbooks;
                    if (!File.Exists(filePath))
                    {
                        File.Copy(AppDomain.CurrentDomain.BaseDirectory + waveFileName + @".xlsx", filePath, true);
                    }
                    this.workbook = workbooks.Add(filePath); //加载模板
                    waveFileNameDate = date;
                }

                Excel.Sheets sheets = workbook.Sheets;
                Excel.Worksheet worksheet = (Excel.Worksheet)sheets.get_Item(1); //第一个工作薄。
                if (worksheet == null)
                {
                    MessageBox.Show("无法打开 Worksheet 对象，请确认 Excel 文件是否正常");
                    return; //工作薄中没有工作表.
                }

                int columnIndex = 1; // A列的索引是1
                int columnCount = CountColumnValues(worksheet, columnIndex);
                if ((sensorDeviceDatas != null) && (sensorDeviceDatas.Count > 0))
                {
                    //写入数值
                    for (int i = 0; i < sensorDeviceDatas.Count; i++)
                    {
                        worksheet.Cells[columnCount + 1 + i, 1] = sensorDeviceDatas[i].collect_datetime;
                        worksheet.Cells[columnCount + 1 + i, 2] = sensorDeviceDatas[i].collect_time;
                        worksheet.Cells[columnCount + 1 + i, 3] = sensorDeviceDatas[i].channel_id;
                        worksheet.Cells[columnCount + 1 + i, 4] = sensorDeviceDatas[i].sensor_type;
                        worksheet.Cells[columnCount + 1 + i, 5] = sensorDeviceDatas[i].sensor_count;
                        worksheet.Cells[columnCount + 1 + i, 6] = sensorDeviceDatas[i].sensor_index;
                        worksheet.Cells[columnCount + 1 + i, 7] = sensorDeviceDatas[i].sensor_id;
                        worksheet.Cells[columnCount + 1 + i, 8] = sensorDeviceDatas[i].sensor_name;
                        worksheet.Cells[columnCount + 1 + i, 9] = sensorDeviceDatas[i].wave_length1;
                        worksheet.Cells[columnCount + 1 + i, 10] = sensorDeviceDatas[i].wave_length2;
                        worksheet.Cells[columnCount + 1 + i, 11] = sensorDeviceDatas[i].wave_length3;
                        worksheet.Cells[columnCount + 1 + i, 12] = sensorDeviceDatas[i].count_value1;
                        worksheet.Cells[columnCount + 1 + i, 13] = sensorDeviceDatas[i].count_value2;
                        worksheet.Cells[columnCount + 1 + i, 14] = sensorDeviceDatas[i].count_value3;
                    }
                    worksheet.Columns.EntireColumn.AutoFit();//列宽自适应
                }
                this.workbook.Saved = true;
                this.workbook.SaveAs(filePath);
            }
            catch (Exception ex)
            {
                bool isUnlocked = FileUnlocker.UnlockFile(filePath);
                if (isUnlocked)
                {
                    this.workbook.SaveAs(filePath);
                }
                else
                {
                    MessageBox.Show("存储 Excel 文件时出错,文件可能正被打开！\n" + ex.Message);
                    log.Error(ex.Message);
                    return;
                }
            }
        }

        private int CountColumnValues(Excel.Worksheet worksheet, int columnIndex)
        {
            int valueCount = 0;
            try
            {
                Excel.Range usedRange = worksheet.UsedRange;
                // 获取列的范围
                Excel.Range columnRange = (Excel.Range)worksheet.Columns[columnIndex];
                int lastRow = columnRange.Cells.SpecialCells(Excel.XlCellType.xlCellTypeLastCell).Row;

                // 遍历列中的所有单元格
                for (int row = 1; row <= lastRow; row++)
                {
                    Excel.Range cell = (Excel.Range)worksheet.Cells[row, columnIndex];
                    if (cell.Value2 != null && !cell.Value2.ToString().Trim().Equals(""))
                    {
                        valueCount++;
                    }
                }
                System.Runtime.InteropServices.Marshal.ReleaseComObject(columnRange);
                System.Runtime.InteropServices.Marshal.ReleaseComObject(usedRange);
            }
            catch (Exception ex)
            {
                log.Error(ex.Message);
            }
            return valueCount;
        }

        public void SaveSensorDeviceDataToMysql(List<SensorDeviceData> sensorDeviceDataList)
        {
            if (isSaveDataToMysql)
            {
                foreach (SensorDeviceData sensorDeviceData in sensorDeviceDataList)
                {
                    MainForm.db.ExecuteSql(
                        MainForm.db.Insert("sensor_device_data")
                        .SetColumn("collect_time", sensorDeviceData.collect_time)
                        .SetColumn("collect_datetime", sensorDeviceData.collect_datetime)
                        .SetColumn("channel_id", sensorDeviceData.channel_id)
                        .SetColumn("sensor_type", sensorDeviceData.sensor_type)
                        .SetColumn("sensor_count", sensorDeviceData.sensor_count)
                        .SetColumn("sensor_index", sensorDeviceData.sensor_index)
                        .SetColumn("sensor_id", sensorDeviceData.sensor_id)
                        .SetColumn("sensor_name", sensorDeviceData.sensor_name)
                        .SetColumn("count_value1", sensorDeviceData.count_value1)
                        .SetColumn("count_value2", sensorDeviceData.count_value2)
                        .SetColumn("count_value3", sensorDeviceData.count_value3)
                        .SetColumn("wave_length1", sensorDeviceData.wave_length1)
                        .SetColumn("wave_length2", sensorDeviceData.wave_length2)
                        .SetColumn("wave_length3", sensorDeviceData.wave_length3)
                        .ToSql());
                }
            }
        }

        public void SaveRasterWaveDataToMysql(string[] waveValues, string[] count_values, long nowTime, int sensorType)
        {
            if (isSaveDataToMysql)
            {
                    MainForm.db.ExecuteSql(
                        MainForm.db.Insert("raster_wave_normal")
                        .SetColumn("collect_time", nowTime)
                        .SetColumn("collect_datetime", (new DateTime(1970, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc).AddMilliseconds((long)nowTime).ToLocalTime()).ToString("yyyy-MM-dd HH:mm:ss"))
                        .SetColumn("channel_id", waveValues[0])
                        .SetColumn("raster_type", sensorType)
                        .SetColumn("raster_count", waveValues[1])
                        .SetColumn("wave_length1", waveValues[2])
                        .SetColumn("wave_length2", waveValues[3])
                        .SetColumn("wave_length3", waveValues[4])
                        .SetColumn("wave_length4", waveValues[5])
                        .SetColumn("wave_length5", waveValues[6])
                        .SetColumn("wave_length6", waveValues[7])
                        .SetColumn("wave_length7", waveValues[8])
                        .SetColumn("wave_length8", waveValues[9])
                        .SetColumn("wave_length9", waveValues[10])
                        .SetColumn("wave_length10", waveValues[11])
                        .SetColumn("wave_length11", waveValues[12])
                        .SetColumn("wave_length12", waveValues[13])
                        .SetColumn("wave_length13", waveValues[14])
                        .SetColumn("wave_length14", waveValues[15])
                        .SetColumn("wave_length15", waveValues[16])
                        .SetColumn("wave_length16", waveValues[17])
                        .ToSql());
            }
        }

        public static void SendEmail(string host, int port, string fromEmail, string password, string toEmail, string subject, string body)
        {
            try
            {
                // 创建邮件消息
                MailMessage mail = new MailMessage();
                mail.From = new MailAddress(fromEmail);
                mail.To.Add(toEmail);
                mail.Subject = subject;
                mail.Body = body;

                // 设置SMTP客户端
                using (SmtpClient client = new SmtpClient(host, port))
                {
                    client.Credentials = new NetworkCredential(fromEmail, password);
                    client.EnableSsl = true; // 如果SMTP服务器需要安全连接，则启用
                    // 发送邮件
                    client.Send(mail);
                }
            }
            catch (Exception ex)
            {
                log.Error(ex.Message);
            }
            finally
            {

            }
        }

        public static void SendSms(string phoneNumber, string[] templateParamSet)
        {
            try
            {
                // 必要步骤：
                // 实例化一个认证对象，入参需要传入腾讯云账户密钥对 SecretId，SecretKey。
                // 为了保护密钥安全，建议将密钥设置在环境变量中或者配置文件中。
                // 硬编码密钥到代码中有可能随代码泄露而暴露，有安全隐患，并不推荐。
                // 这里采用的是从环境变量读取的方式，需要在环境变量中先设置这两个值。
                // SecretId、SecretKey 查询：https://console.cloud.tencent.com/cam/capi
                Credential cred = new Credential
                {
                    //SecretId = Environment.GetEnvironmentVariable("TENCENTCLOUD_SECRET_ID"),
                    //SecretKey = Environment.GetEnvironmentVariable("TENCENTCLOUD_SECRET_KEY")
                    SecretId = "AKIDaRMzSimmfMqDWfcQ1ShkutiNrAIFzXuA",
                    SecretKey = "CAyc6lCQ2cLypW2OaeowtfJqCOemkXBg"
                };

                /* 非必要步骤:
                 * 实例化一个客户端配置对象，可以指定超时时间等配置 */
                ClientProfile clientProfile = new ClientProfile();
                /* SDK默认用TC3-HMAC-SHA256进行签名
                 * 非必要请不要修改这个字段 */
                clientProfile.SignMethod = ClientProfile.SIGN_TC3SHA256;
                /* 非必要步骤
                 * 实例化一个客户端配置对象，可以指定超时时间等配置 */
                HttpProfile httpProfile = new HttpProfile();
                /* SDK默认使用POST方法。
                 * 如果您一定要使用GET方法，可以在这里设置。GET方法无法处理一些较大的请求 */
                httpProfile.ReqMethod = "POST";
                httpProfile.Timeout = 10; // 请求连接超时时间，单位为秒(默认60秒)
                /* 指定接入地域域名，默认就近地域接入域名为 sms.tencentcloudapi.com ，也支持指定地域域名访问，例如广州地域的域名为 sms.ap-guangzhou.tencentcloudapi.com */
                httpProfile.Endpoint = "sms.tencentcloudapi.com";
                // 代理服务器，当您的环境下有代理服务器时设定（无需要直接忽略）
                // httpProfile.WebProxy = Environment.GetEnvironmentVariable("HTTPS_PROXY");

                clientProfile.HttpProfile = httpProfile;
                /* 实例化要请求产品(以sms为例)的client对象
                 * 第二个参数是地域信息，可以直接填写字符串ap-guangzhou，支持的地域列表参考 https://cloud.tencent.com/document/api/382/52071#.E5.9C.B0.E5.9F.9F.E5.88.97.E8.A1.A8 */
                SmsClient client = new SmsClient(cred, "ap-nanjing", clientProfile);

                /* 实例化一个请求对象，根据调用的接口和实际情况，可以进一步设置请求参数
                 * 您可以直接查询SDK源码确定SendSmsRequest有哪些属性可以设置
                 * 属性可能是基本类型，也可能引用了另一个数据结构
                 * 推荐使用IDE进行开发，可以方便的跳转查阅各个接口和数据结构的文档说明 */
                SendSmsRequest req = new SendSmsRequest();

                /* 基本类型的设置:
                 * SDK采用的是指针风格指定参数，即使对于基本类型您也需要用指针来对参数赋值。
                 * SDK提供对基本类型的指针引用封装函数
                 * 帮助链接：
                 * 短信控制台: https://console.cloud.tencent.com/smsv2
                 * 腾讯云短信小助手: https://cloud.tencent.com/document/product/382/3773#.E6.8A.80.E6.9C.AF.E4.BA.A4.E6.B5.81 */
                /* 短信应用ID: 短信SdkAppId在 [短信控制台] 添加应用后生成的实际SdkAppId，示例如1400006666 */
                // 应用 ID 可前往 [短信控制台](https://console.cloud.tencent.com/smsv2/app-manage) 查看
                req.SmsSdkAppId = "1400957364";

                /* 短信签名内容: 使用 UTF-8 编码，必须填写已审核通过的签名 */
                // 签名信息可前往 [国内短信](https://console.cloud.tencent.com/smsv2/csms-sign) 或 [国际/港澳台短信](https://console.cloud.tencent.com/smsv2/isms-sign) 的签名管理查看
                req.SignName = "屏优多科技";

                /* 模板 ID: 必须填写已审核通过的模板 ID */
                // 模板 ID 可前往 [国内短信](https://console.cloud.tencent.com/smsv2/csms-template) 或 [国际/港澳台短信](https://console.cloud.tencent.com/smsv2/isms-template) 的正文模板管理查看
                req.TemplateId = "2342074";

                /* 模板参数: 模板参数的个数需要与 TemplateId 对应模板的变量个数保持一致，若无模板参数，则设置为空 */
                req.TemplateParamSet = templateParamSet;

                /* 下发手机号码，采用 E.164 标准，+[国家或地区码][手机号]
                 * 示例如：+8613711112222， 其中前面有一个+号 ，86为国家码，13711112222为手机号，最多不要超过200个手机号*/
                req.PhoneNumberSet = new System.String[] { "+86" + phoneNumber };

                /* 用户的 session 内容（无需要可忽略）: 可以携带用户侧 ID 等上下文信息，server 会原样返回 */
                req.SessionContext = "告警";

                /* 短信码号扩展号（无需要可忽略）: 默认未开通，如需开通请联系 [腾讯云短信小助手] */
                req.ExtendCode = "";

                /* 国内短信无需填写该项；国际/港澳台短信已申请独立 SenderId 需要填写该字段，默认使用公共 SenderId，无需填写该字段。注：月度使用量达到指定量级可申请独立 SenderId 使用，详情请联系 [腾讯云短信小助手](https://cloud.tencent.com/document/product/382/3773#.E6.8A.80.E6.9C.AF.E4.BA.A4.E6.B5.81)。 */
                req.SenderId = "";

                SendSmsResponse resp = client.SendSmsSync(req);

                // 输出json格式的字符串回包
                log.Info(AbstractModel.ToJsonString(resp));

                /* 当出现以下错误码时，快速解决方案参考
                 * [FailedOperation.SignatureIncorrectOrUnapproved](https://cloud.tencent.com/document/product/382/9558#.E7.9F.AD.E4.BF.A1.E5.8F.91.E9.80.81.E6.8F.90.E7.A4.BA.EF.BC.9Afailedoperation.signatureincorrectorunapproved-.E5.A6.82.E4.BD.95.E5.A4.84.E7.90.86.EF.BC.9F)
                 * [FailedOperation.TemplateIncorrectOrUnapproved](https://cloud.tencent.com/document/product/382/9558#.E7.9F.AD.E4.BF.A1.E5.8F.91.E9.80.81.E6.8F.90.E7.A4.BA.EF.BC.9Afailedoperation.templateincorrectorunapproved-.E5.A6.82.E4.BD.95.E5.A4.84.E7.90.86.EF.BC.9F)
                 * [UnauthorizedOperation.SmsSdkAppIdVerifyFail](https://cloud.tencent.com/document/product/382/9558#.E7.9F.AD.E4.BF.A1.E5.8F.91.E9.80.81.E6.8F.90.E7.A4.BA.EF.BC.9Aunauthorizedoperation.smssdkappidverifyfail-.E5.A6.82.E4.BD.95.E5.A4.84.E7.90.86.EF.BC.9F)
                 * [UnsupportedOperation.ContainDomesticAndInternationalPhoneNumber](https://cloud.tencent.com/document/product/382/9558#.E7.9F.AD.E4.BF.A1.E5.8F.91.E9.80.81.E6.8F.90.E7.A4.BA.EF.BC.9Aunsupportedoperation.containdomesticandinternationalphonenumber-.E5.A6.82.E4.BD.95.E5.A4.84.E7.90.86.EF.BC.9F)
                 * 更多错误，可咨询[腾讯云助手](https://tccc.qcloud.com/web/im/index.html#/chat?webAppId=8fa15978f85cb41f7e2ea36920cb3ae1&title=Sms)
                 */
            }
            catch (Exception ex)
            {
                log.Error(ex.Message);
            }
            //Console.Read();
        }

        public static void PullSmsSendStatus()
        {
            try
            {
                // 必要步骤：
                // 实例化一个认证对象，入参需要传入腾讯云账户密钥对 SecretId，SecretKey。
                // 为了保护密钥安全，建议将密钥设置在环境变量中或者配置文件中。
                // 硬编码密钥到代码中有可能随代码泄露而暴露，有安全隐患，并不推荐。
                // 这里采用的是从环境变量读取的方式，需要在环境变量中先设置这两个值。
                // SecretId、SecretKey 查询：https://console.cloud.tencent.com/cam/capi
                Credential cred = new Credential
                {
                    //SecretId = Environment.GetEnvironmentVariable("TENCENTCLOUD_SECRET_ID"),
                    //SecretKey = Environment.GetEnvironmentVariable("TENCENTCLOUD_SECRET_KEY")
                    SecretId = "AKIDaRMzSimmfMqDWfcQ1ShkutiNrAIFzXuA",
                    SecretKey = "CAyc6lCQ2cLypW2OaeowtfJqCOemkXBg"
                };
                /* 非必要步骤:
                 * 实例化一个客户端配置对象，可以指定超时时间等配置 */
                ClientProfile clientProfile = new ClientProfile();
                /* SDK 默认用 TC3-HMAC-SHA256 进行签名
                 * 非必要请不要修改该字段 */
                clientProfile.SignMethod = ClientProfile.SIGN_TC3SHA256;
                /* 非必要步骤
                 * 实例化一个客户端配置对象，可以指定超时时间等配置 */
                HttpProfile httpProfile = new HttpProfile();
                /* SDK 默认使用 POST 方法
                 * 如需使用 GET 方法，可以在此处设置，但 GET 方法无法处理较大的请求 */
                httpProfile.ReqMethod = "POST";
                httpProfile.Timeout = 30; // 请求连接超时时间，单位为秒(默认60秒)
                /* 指定接入地域域名，默认就近地域接入域名为 sms.tencentcloudapi.com ，也支持指定地域域名访问，例如广州地域的域名为 sms.ap-guangzhou.tencentcloudapi.com */
                httpProfile.Endpoint = "sms.tencentcloudapi.com";
                // 代理服务器，当您的环境下有代理服务器时设定
                // httpProfile.WebProxy = Environment.GetEnvironmentVariable("HTTPS_PROXY");
                clientProfile.HttpProfile = httpProfile;
                /* 实例化 SMS 的 client 对象
                 * 第二个参数是地域信息，可以直接填写字符串ap-guangzhou，支持的地域列表参考 https://cloud.tencent.com/document/api/382/52071#.E5.9C.B0.E5.9F.9F.E5.88.97.E8.A1.A8 */
                SmsClient client = new SmsClient(cred, "ap-guangzhou", clientProfile);
                /* 实例化一个请求对象，根据调用的接口和实际情况，可以进一步设置请求参数
                 * 您可以直接查询 SDK 源码确定 SendSmsRequest 有哪些属性可以设置
                 * 属性可能是基本类型，也可能引用了另一个数据结构
                 * 推荐使用 IDE 进行开发，可以方便地跳转查阅各个接口和数据结构的文档说明 */
                PullSmsSendStatusRequest req = new PullSmsSendStatusRequest();

                /* 基本类型的设置:
                 * SDK 采用的是指针风格指定参数，即使对于基本类型也需要用指针来对参数赋值
                 * SDK 提供对基本类型的指针引用封装函数
                 * 帮助链接：
                 * 短信控制台：https://console.cloud.tencent.com/smsv2
                 * 腾讯云短信小助手：https://cloud.tencent.com/document/product/382/3773#.E6.8A.80.E6.9C.AF.E4.BA.A4.E6.B5.81 */

                // 设置拉取最大条数，最多100条
                req.Limit = 100;
                /* 短信应用 ID: 在 [短信控制台] 添加应用后生成的实际 SdkAppId，例如1400006666 */
                req.SmsSdkAppId = "1400957364";
                // 通过 client 对象调用 PullSmsSendStatus 方法发起请求，注意请求方法名与请求对象是对应的
                // 返回的 resp 是一个 PullSmsSendStatusResponse 类的实例，与请求对象对应
                PullSmsSendStatusResponse resp = client.PullSmsSendStatusSync(req);
                // 输出 JSON 格式的字符串回包
                log.Info(AbstractModel.ToJsonString(resp));
            }
            catch (Exception ex)
            {
                log.Error(ex.Message);
            }
            //Console.Read();
        }

        private void btnCollectWave_Click(object sender, System.EventArgs e)
        {
            try
            {
                bool isOpenServerPort = MainForm.getOpenServerPort();
                if (!isOpenServerPort)
                {
                    MessageBox.Show("请先打开服务端口！", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
                    return;
                }
                Socket serverSocket = MainForm.getServerSocket();
                if (serverSocket == null)
                {
                    return;
                }
                EndPoint endPoint = MainForm.getEndPoint();
                //停用按钮，防止多次点击
                this.btnCollectWave.Enabled = false;
                string msg = this.btnCollectWave.Text;
                if ((!string.IsNullOrEmpty(msg)) && ("开始采集".Equals(msg)))
                {
                    //UI显示
                    this.btnCollectWave.Text = "停止采集";
                    this.btnCollectWave.Enabled = true;
                    this.tbWaveFrequency.Enabled = false;
                    this.tbWaveCollectTimes.Enabled = false;
                    this.cbWaveCollectTimes.Enabled = false;
                    this.tbWaveFilePath.Enabled = false;
                    this.ibOpenFilePath.Enabled = false;
                    this.cbSaveWaveExcel.Enabled = false;

                    //如果不为空
                    byte[] bmsg = { 0x01, 0x0A, 0x55 };
                    if (bmsg != null)
                    {
                        if (this.isSaveWaveToExcel)
                        {
                            CreateExcelDataFile();
                        }

                        //开启接收消息线程
                        receiveThread1 = new Thread(ReceiveMessage);
                        receiveThread1.Start();

                        //发送数据包
                        serverSocket.SendTo(bmsg, endPoint);
                    }
                    else
                    {
                        MessageBox.Show("发送数据格式错误：" + msg, "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
                    }
                }
                else
                {
                    byte[] bmsg = { 0x01, 0x0A, 0x00 };
                    if (bmsg != null)
                    {
                        //UI显示
                        this.btnCollectWave.Text = "开始采集";
                        this.btnCollectWave.Enabled = true;
                        this.tbWaveFrequency.Enabled = true;
                        this.tbWaveCollectTimes.Enabled = true;
                        this.cbWaveCollectTimes.Enabled = true;
                        this.tbWaveFilePath.Enabled = true;
                        this.ibOpenFilePath.Enabled = true;
                        this.cbSaveWaveExcel.Enabled = true;

                        //发送数据包
                        serverSocket.SendTo(bmsg, endPoint);

                        //先关闭线程，再关闭服务器
                        if (receiveThread1 != null)
                        {
                            receiveThread1.Interrupt();
                        }

                        //if (this.isSaveWaveToExcel)
                        //{
                        //    if (this.excelApp != null)
                        //    {
                        //        this.excelApp.DisplayAlerts = false;
                        //        if (this.workbook != null)
                        //        {
                        //            this.workbook.Close(false);
                        //            this.workbook = null;
                        //        }
                        //        this.excelApp.Quit();
                        //        this.excelApp = null;
                        //    }
                        //}
                    }
                    else
                    {
                        MessageBox.Show("发送数据格式错误：" + msg, "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
                    }
                }
            }
            catch (SocketException ex)
            {
                MessageBox.Show("发送数据报时出现异常：" + ex.ErrorCode + "！", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
                log.Error(ex.Message);
            }
            finally
            {
                //按钮启用
                btnCollectWave.Enabled = true;
            }
        }

        private void cbWaveSensorType_SelectedIndexChanged(object sender, EventArgs e)
        {
            this.sensorType = cbWaveSensorType.SelectedIndex;
            if (debug)
            {
                // 假设你在非UI线程上
                if (this.cbWaveSensorType.InvokeRequired)
                {
                    this.cbWaveSensorType.Invoke(new System.Action(() =>
                    {
                        if (this.sensorType != this.cbWaveSensorType.SelectedIndex)
                        {
                            if (this.cbWaveSensorType.SelectedIndex == 3)
                            {
                                try
                                {
                                    InitChartConfig(channelIndex, 3);
                                }
                                catch (Exception ex)
                                {
                                    log.Error(ex.Message);
                                }
                                finally
                                {
                                }
                            }
                            else if (this.sensorType == 3)
                            {
                                try
                                {
                                     InitChartConfig();
                                }
                                catch (Exception ex)
                                {
                                    log.Error(ex.Message);
                                }
                                finally
                                {
                                }
                            }
                            else
                            {
                                try
                                {
                                    InitChartConfig();
                                }
                                catch (Exception ex)
                                {
                                    log.Error(ex.Message);
                                }
                                finally
                                {
                                }
                            }
                            this.sensorType = this.cbWaveSensorType.SelectedIndex;
                        }
                    }));
                }
                else
                {
                    // 直接进行操作，因为当前线程就是UI线程
                    if (this.sensorType != this.cbWaveSensorType.SelectedIndex)
                    {
                        if (this.cbWaveSensorType.SelectedIndex == 3)
                        {
                            try
                            {
                                InitChartConfig(channelIndex, 3);
                            }
                            catch (Exception ex)
                            {
                                log.Error(ex.Message);
                            }
                            finally
                            {
                            }
                        }
                        else
                        {
                            try
                            {
                                InitChartConfig();
                            }
                            catch (Exception ex)
                            {
                                log.Error(ex.Message);
                            }
                            finally
                            {
                            }
                        }
                        this.sensorType = this.cbWaveSensorType.SelectedIndex;
                    }
                }
            }
            try
            {
                Configuration config = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);
                AppSettingsSection app = config.AppSettings;
                app.Settings["cbWaveSensorType"].Value = this.cbWaveSensorType.SelectedIndex + "";
                config.Save(ConfigurationSaveMode.Modified);
            }
            catch (Exception ex)
            {
                log.Error(ex.Message);
            }
        }
        
        private void cbWaveChannelSellect_SelectedIndexChanged(object sender, EventArgs e)
        {
            // 假设你在非UI线程上
            if (this.cbWaveChannelSellect.InvokeRequired)
            {
                this.cbWaveChannelSellect.Invoke(new System.Action(() =>
                {
                    if (this.channelIndex != this.cbWaveChannelSellect.SelectedIndex)
                    {
                        this.channelIndex = this.cbWaveChannelSellect.SelectedIndex;
                        try
                        {
                            InitChartConfig();
                        }
                        catch (Exception ex)
                        {
                            log.Error(ex.Message);
                        }
                        finally
                        {
                        }
                    }
                }));
            }
            else
            {
                // 直接进行操作，因为当前线程就是UI线程
                if (this.channelIndex != this.cbWaveChannelSellect.SelectedIndex)
                {
                    this.channelIndex = this.cbWaveChannelSellect.SelectedIndex;
                    try
                    {
                        InitChartConfig();
                    }
                    catch (Exception ex)
                    {
                        log.Error(ex.Message);
                    }
                    finally
                    {
                    }
                }
            }
            try
            {
                Configuration config = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);
                AppSettingsSection app = config.AppSettings;
                app.Settings["cbWaveChannelSellect"].Value = this.cbWaveChannelSellect.Text;
                config.Save(ConfigurationSaveMode.Modified);
            }
            catch (Exception ex)
            {
                log.Error(ex.Message);
            }
        }

        private void cbWaveSensorSellect_SelectedIndexChanged(object sender, EventArgs e)
        {
            // 假设你在非UI线程上
            if (this.cbWaveSensorSellect.InvokeRequired)
            {
                this.cbWaveSensorSellect.Invoke(new System.Action(() =>
                {
                    if (this.rasterIndex != this.cbWaveSensorSellect.SelectedIndex)
                    {
                        this.rasterIndex = this.cbWaveSensorSellect.SelectedIndex;
                        try
                        {
                            InitChartConfig();
                        }
                        catch (Exception ex)
                        {
                            log.Error(ex.Message);
                        }
                        finally
                        {
                        }
                    }
                }));
            }
            else
            {
                // 直接进行操作，因为当前线程就是UI线程
                if (this.rasterIndex != this.cbWaveSensorSellect.SelectedIndex)
                {
                    this.rasterIndex = this.cbWaveSensorSellect.SelectedIndex;
                    try
                    {
                        InitChartConfig();
                    }
                    catch (Exception ex)
                    {
                        log.Error(ex.Message);
                    }
                    finally
                    {
                    }
                }
            }
            try
            {
                Configuration config = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);
                AppSettingsSection app = config.AppSettings;
                app.Settings["cbWaveSensorSellect"].Value = this.cbWaveSensorSellect.Text;
                config.Save(ConfigurationSaveMode.Modified);
            }
            catch (Exception ex)
            {
                log.Error(ex.Message);
            }
        }

        private void tbWaveFrequency_TextChanged(object sender, EventArgs e)
        {
            try
            {
                if (this.tbWaveFrequency.Text.Length > 0)
                {
                    long _frequency = Convert.ToInt64(this.tbWaveFrequency.Text);
                    //转换成长整型
                    if (this.frequency != _frequency)
                    {
                        this.frequency = _frequency;
                        //this.intervalTime = 1000 / this.frequency;
                        //this.xCount = this.showTimes * this.frequency;
                        this.xCount = this.frequency;
                    }
                    Configuration config = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);
                    AppSettingsSection app = config.AppSettings;
                    app.Settings["tbWaveFrequency"].Value = this.tbWaveFrequency.Text;
                    config.Save(ConfigurationSaveMode.Modified);
                }
            }
            catch (Exception ex)
            {
                log.Error(ex.Message);
            }
        }

        private void cbSaveWaveExcel_CheckedChanged(object sender, EventArgs e)
        {
            try
            {
                this.isSaveWaveToExcel = this.cbSaveWaveExcel.Checked;
                this.tbWaveFilePath.Enabled = this.cbSaveWaveExcel.Checked;
                this.ibOpenFilePath.Enabled = this.cbSaveWaveExcel.Checked;

                Configuration config = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);
                AppSettingsSection app = config.AppSettings;
                app.Settings["cbSaveWaveExcel"].Value = this.cbSaveWaveExcel.Checked.ToString();
                config.Save(ConfigurationSaveMode.Modified);

                //if (this.isSaveWaveToExcel)
                //{
                //    CreateExcelDataFile();
                //}
                //else
                //{
                //    if (excelApp != null)
                //    {
                //        excelApp.DisplayAlerts = false;
                //        if (workbook != null)
                //        {
                //            workbook.Close(false);
                //            workbook = null;
                //        }
                //        excelApp.Quit();
                //        excelApp = null;
                //    }
                //}
            }
            catch (Exception ex)
            {
                log.Error(ex.Message);
            }
        }

        private void tbWaveFilePath_TextChanged(object sender, EventArgs e)
        {
            try
            {
                if (this.tbWaveFilePath.Text.Length > 0)
                {
                    if (!waveFilePath.Equals(this.tbWaveFilePath.Text))
                    {
                        waveFilePath = this.tbWaveFilePath.Text;
                        //if (this.isSaveWaveToExcel)
                        //{
                        //    if (this.excelApp != null)
                        //    {
                        //        this.excelApp.DisplayAlerts = false;
                        //        if (this.workbook != null)
                        //        {
                        //            this.workbook.Close(false);
                        //            this.workbook = null;
                        //        }
                        //        this.excelApp.Quit();
                        //        this.excelApp = null;
                        //    }
                        //    CreateExcelDataFile();
                        //}
                        Configuration config = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);
                        AppSettingsSection app = config.AppSettings;
                        app.Settings["tbWaveFilePath"].Value = this.tbWaveFilePath.Text;
                        config.Save(ConfigurationSaveMode.Modified);
                    }
                }
            }
            catch (Exception ex)
            {
                log.Error(ex.Message);
            }
        }

        private void cbWaveCollectTimes_CheckedChanged(object sender, EventArgs e)
        {
            try
            {
                this.tbWaveCollectTimes.Enabled = this.cbWaveCollectTimes.Checked;
                this.isWaveCollectTimes = this.cbWaveCollectTimes.Checked;
                Configuration config = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);
                AppSettingsSection app = config.AppSettings;
                app.Settings["cbWaveCollectTimes"].Value = this.cbWaveCollectTimes.Checked.ToString();
                config.Save(ConfigurationSaveMode.Modified);
            }
            catch (Exception ex)
            {
                log.Error(ex.Message);
            }
        }

        private void tbWaveCollectTimes_TextChanged(object sender, EventArgs e)
        {
            try
            {
                if (this.tbWaveCollectTimes.Text.Length > 0)
                {
                    this.waveCollectTimes = Convert.ToInt32(this.tbWaveCollectTimes.Text);
                    Configuration config = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);
                    AppSettingsSection app = config.AppSettings;
                    app.Settings["tbWaveCollectTimes"].Value = this.tbWaveCollectTimes.Text;
                    config.Save(ConfigurationSaveMode.Modified);
                }
            }
            catch (Exception ex)
            {
                log.Error(ex.Message);
            }
        }

        private void ibOpenFilePath_Click(object sender, EventArgs e)
        {
            try
            {
                FolderBrowserDialog folderBrowserDialog = new FolderBrowserDialog();
                folderBrowserDialog.ShowDialog();
                this.tbWaveFilePath.Text = folderBrowserDialog.SelectedPath; //获得选择的文件夹路径
            }
            catch (Exception ex)
            {
                log.Error(ex.Message);
            }
        }

        private void cbSimulationTest_CheckedChanged(object sender, EventArgs e)
        {
            this.debug = this.cbSimulationTest.Checked;
        }

        public static bool getIsAlarmNotify()
        {
            return isAlarmNotify;
        }

        public static void setIsAlarmNotify(bool param)
        {
            isAlarmNotify = param;
        }

        public static double getAxialForceExceeds()
        {
            return axialForceExceeds;
        }

        public static void setAxialForceExceeds(double param)
        {
            axialForceExceeds = param;
        }

        public static int getRepeatTimes()
        {
            return repeatTimes;
        }

        public static void setRepeatTimes(int param)
        {
            repeatTimes = param;
        }

        public static bool getIsAlarmPhone()
        {
            return isAlarmPhone;
        }
        
        public static void setIsAlarmPhone(bool param)
        {
            isAlarmPhone = param;
        }
        
        public static string getAlarmPhone()
        {
            return alarmPhone;
        }
        
        public static void setAlarmPhone(string param)
        {
            alarmPhone = param;
        }
        
        public static bool getIsAlarmEmail()
        {
            return isAlarmEmail;
        }
        
        public static void setIsAlarmEmail(bool param)
        {
            isAlarmEmail = param;
        }
        
        public static string getAlarmEmail()
        {
            return alarmEmail;
        }
        
        public static void setAlarmEmail(string param)
        {
            alarmEmail = param;
        }
        
        public static double getTempStartWave()
        {
            return tempStartWave;
        }
        public static void setTempStartWave(double param)
        {
            tempStartWave = param;
        }
        public static double getTempStartValue()
        {
            return tempStartValue;
        }
        public static void setTempStartValue(double param)
        {
            tempStartValue = param;
        }
    }
}

public class SensorWaveData
{
    //采集时间
    public long timestamp { get; set; }
    //通道ID
    public int channelId { get; set; }
    //波长数量
    public int waveCnt { get; set; }
    //波长数组
    public double[] waveLengths { get; set; }

}


public class DeviceData
{
    //传感器ID
    public int deviceId { get; set; }
    //传感器类型
    public int deviceType { get; set; }
    //传感器名称
    public string name { get; set; }
    //采集时间
    public long timestamp { get; set; }
    //结果
    public double value { get; set; }
    //结果1
    public double value1 { get; set; }
    //结果2
    public double value2 { get; set; }
    //光栅波长1
    public double wave1 { get; set; }
    //光栅波长2
    public double wave2 { get; set; }
    //光栅波长3
    public double wave3 { get; set; }

    public override string ToString()
    {
        return deviceId + ", " + deviceType + ", " + name + ", " + timestamp + ", " + value + ", " + value1 + ", " + value2 + ", " + wave1 + ", " + wave2 + ", " + wave3;
    }
}

public class SensorDeviceData
{
    //采集时间
    public string collect_datetime { get; set; }
    //采集时间
    public long collect_time { get; set; }
    //通道ID
    public int channel_id { get; set; }
    //传感器类型
    public int sensor_type { get; set; }
    //传感器数量
    public int sensor_count { get; set; }
    //传感器索引
    public int sensor_index { get; set; }
    //传感器ID
    public int sensor_id { get; set; }
    //传感器名称
    public string sensor_name { get; set; }
    //光栅波长1
    public double wave_length1 { get; set; }
    //光栅波长2
    public double wave_length2 { get; set; }
    //光栅波长3
    public double wave_length3 { get; set; }
    //结果1
    public double count_value1 { get; set; }
    //结果2
    public double count_value2 { get; set; }
    //结果3
    public double count_value3 { get; set; }

    public override string ToString()
    {
        return collect_datetime + ", " + collect_time + ", " + channel_id + ", " + sensor_type + ", " + sensor_count + ", " + sensor_index + ", " + sensor_id + ", " + sensor_name + ", " + wave_length1 + ", " + wave_length2 + ", " + wave_length3 + ", " + count_value1 + ", " + count_value2 + ", " + count_value3;
    }
}